Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code First: which DataType attribute for DateTime2?

Sometime when using Entity Framework Code First, the default conventions do not create the database type you want. For instance by default a property of type System.DateTime creates a database column of type DateTime. What to do if you want it to have a type of datetime2 (the DateTime type that has no problems with time zones and daylight saving time)?

It is possible to specify the required database type with Data Annotations using a DataTypeAtrribute. One of the constructors of DataTypeAttribute accepts a parameter DataType Enumeration. So one could specify something like:

[DataType(DataType.DateTime)]
public DateTime DateOfBirth {get; set;}

The DataType enumeration type contains a lot of types, however it is missing a value for DateTime2.

Another approach would be using Fluent API. Create a DateTime2 in method DBContext.OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Student>().Property(p => p.BirthDate)
        .HasColumnType("datetime2");
}

The DataTypeAttribute has a second constructor that accepts a string. This string is defined as

The name of the custom field template to associate with the data field.

So one would assume that the following would be enough to create a datetime2:

[DataType("datetime2")]
public DateTime DateOfBirth {get; set;}

Alas, this doesn't work. The created column still has the DateTime format.

Question: which string to use in the constructor to create a datetime2?

like image 424
Harald Coppoolse Avatar asked Nov 03 '15 09:11

Harald Coppoolse


People also ask

Which data annotation attribute can be used to define a primary key property?

You can use the key annotation to specify which property is to be used as the EntityKey. If you are using code first's database generation feature, the Blog table will have a primary key column named PrimaryTrackingKey, which is also defined as Identity by default.

Is column a data annotation attribute?

The Column attribute can be applied to one or more properties in an entity class to configure the corresponding column name, data type and order in a database table.

What is meant by primary key in Entity Framework Code First?

The Code First primary key convention is: Property with name " Id " or {class name} + " Id " will act as the primary key for that entity. If you will run the application, it will create _MigrationHistory and Students tables where " StudentId " is the primary key of the Students table.


2 Answers

The DataType attribute is not used for column type mapping for Code First:

The Column annotation is a more adept in specifying the attributes of a mapped column. You can stipulate a name, data type or even the order in which a column appears in the table. [...] Don’t confuse Column’s TypeName attribute with the DataType DataAnnotation. DataType is an annotation used for the UI and is ignored by code first.

So:

[Column(TypeName="datetime2")] 
like image 193
CodeCaster Avatar answered Sep 28 '22 23:09

CodeCaster


For those still interested in how to define column types for properties. From EF version 6.0 onwards you can define that every value of some type should have some database type.

This is done In DbContext.OnModelCreating using DbModelBuilder.Properties.

If you do this, you don't have to write attributes nor fluent API for every DateTime. It is easier to be consistent and let all DateTime have the same column type. Similarly you can give all decimals the same precision, even if decimals are added in future.

Suppose you want to define that every System.DateTime should have column type DateTime2; every System.Decimal should have a column type with a specified precision. In DbContext you would write:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // every property of type DateTime should have a column type of "datetime2":
    modelBuilder.Properties<DateTime>()
      .Configure(property => property.HasColumnType("datetime2"));
    // every property of type decimal should have a precision of 19
    // and a scale of 8:
    modelBuilder.Properties<decimal>()
        .Configure(property => property.HasPrecision(19, 8));
}
like image 28
Harald Coppoolse Avatar answered Sep 29 '22 00:09

Harald Coppoolse