Setting the default value of a DateTime Property to DateTime.Now inside the System.ComponentModel Default Value Attrbute

Viewed 211416

Does any one know how I can specify the Default value for a DateTime property using the System.ComponentModel DefaultValue Attribute?

for example I try this:

[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))]
public DateTime DateCreated { get; set; }

And it expects the value to be a constant expression.

This is in the context of using with ASP.NET Dynamic Data. I do not want to scaffold the DateCreated column but simply supply the DateTime.Now if it is not present. I am using the Entity Framework as my Data Layer

Cheers,

Andrew

24 Answers

You cannot do this with an attribute because they are just meta information generated at compile time. Just add code to the constructor to initialize the date if required, create a trigger and handle missing values in the database, or implement the getter in a way that it returns DateTime.Now if the backing field is not initialized.

public DateTime DateCreated
{
   get
   {
      return this.dateCreated.HasValue
         ? this.dateCreated.Value
         : DateTime.Now;
   }

   set { this.dateCreated = value; }
}

private DateTime? dateCreated = null;

I have tested this on EF core 2.1

Here you cannot use either Conventions or Data Annotations. You must use the Fluent API.

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Created)
            .HasDefaultValueSql("getdate()");
    }
}

Official doc

I faced the same issue, but the one which works for me best is below:

public DateTime CreatedOn { get; set; } = DateTime.Now;

Using EntityTypeConfiguration, I get it like this:

public class UserMap : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        //throw new NotImplementedException();
        builder.Property(u => u.Id).ValueGeneratedOnAdd();
        builder.Property(u => u.Name).IsRequired().HasMaxLength(100);
        builder.HasIndex(u => u.Email).IsUnique();
        builder.Property(u => u.Status).IsRequired();
        builder.Property(u => u.Password).IsRequired();
        builder.Property(u => u.Registration).HasDefaultValueSql("getdate()");

        builder.HasMany(u => u.DrawUser).WithOne(u => u.User);

        builder.ToTable("User");
    }
}

How you deal with this at the moment depends on what model you are using Linq to SQL or EntityFramework?

In L2S you can add

public partial class NWDataContext
{
    partial void InsertCategory(Category instance)
    {
        if(Instance.Date == null)
            Instance.Data = DateTime.Now;

        ExecuteDynamicInsert(instance);
    }
}

EF is a little more complicated see http://msdn.microsoft.com/en-us/library/cc716714.aspx for more info on EF buisiness logic.

below works in .NET 5.0

        private DateTime _DateCreated= DateTime.Now;
        public DateTime DateCreated
        {
            get
            {
                return this._DateCreated;
            }

            set { this._DateCreated = value; }
        }

Using the Fluent API, in OnModelCreating function in your Context class add following.

 builder.Property(u => u.CreatedAt).ValueGeneratedOnAdd();
 builder.Property(u => u.UpdatedAt).ValueGeneratedOnAddOrUpdate();

Note I'm using a separate type configuration class. If you did right in the function would be like:

builder.Enitity<User>().Property(u => u.CreatedAt).ValueGeneratedOnAdd();
Related