8

I want to create a DateTime field so that it will have a default GETDATE() once it gets to the database. So I did this:

 public class Specialty
 {
     [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
     public DateTime? CreatedDate { get; set; }

     // other properties not shown for brevity.
 }

So I ran Add-Migration in the PM> console. It resulted in this (not all lines are shown) in the Up function:

AddColumn("dbo.Specialty", "CreatedDate", c => c.DateTime());

I understand that nullable of c.DateTime(...) is true by default, so I understand why it's not specified. BUT where is defaultValueSql: "GETDATE()"?

I know I can put it in manually, but that seems to defeat the purpose of Add-Migration and makes [DatabaseGenerated(DatabaseGeneratedOption.Computed)] useless. I know for a fact that defaultValueSql's default is not "GETDATE()" because it doesn't show up when I look at column properties in SQL Management Studio.

What's missing? Does the name "CreatedDate" violate an EF convention, then? Is there another library that I should have referenced besides System.ComponentModel.DataAnnotations.Schema?

Mickael Caruso
  • 8,721
  • 11
  • 40
  • 72
  • possible duplicate of [EF 4.3.1 Migration Exception - AlterColumn defaultValueSql creates same default constraint name for different tables](http://stackoverflow.com/questions/9830216/ef-4-3-1-migration-exception-altercolumn-defaultvaluesql-creates-same-default) – Sherif Ahmed May 01 '14 at 18:25

2 Answers2

12

[DatabaseGenerated(DatabaseGeneratedOption.Computed)] is not useless, it tells the Entity Framework that the column is required in the database but is computed by the database. So it knows that it should create the column in a migration and it knows that it should not try to update its value nor insert a value.

What is missing is that you have to add the computation to the database column. And you do that by modifying the migration:

        AddColumn("dbo.Specialty", 
                  "CreatedDate", 
                  c => c.DateTime(defaultValueSql: "GETDATE()"));

There is currently no way to specify the sql in a data annotation, and I suspect that there never will be because the sql could be database specific, and is therefore best kept within a migration rather than being allowed to leak into the model definition

Colin
  • 22,328
  • 17
  • 103
  • 197
  • So we have to go into Configuration.cs and put that in. I guess I'll have to do that by hand. It's just that tutorials don't tell us this. They state that defaultValueSql: "GETDATE()" will automatically be written by Add-Migration. – Mickael Caruso May 03 '14 at 12:49
  • Just a word of caution -> GETUTCDATE(), in the end, is better than GETDATE(). – tymtam Jun 03 '16 at 01:49
  • @Tymski Yes. Unless you "want to create a `DateTime` field so that it will have a default `GETDATE()` once it gets to the database." – Colin Jun 03 '16 at 08:27
  • @Colin, yes yes, but what I'm saying is that even if you think you want GETDATE() you really want GETUTCDATE(). – tymtam Jun 06 '16 at 02:41
0

I ended up inheriting all entities from a base class, following these instructions.

This means making a custom migration class for the CreatedDate and UpdatedDate column, and it works perfectly with minimal effort.

demoncodemonkey
  • 11,730
  • 10
  • 61
  • 103