实体框架代码“首次日期”字段创建


82

我正在使用Entity Framework Code First方法创建数据库表。以下代码DATETIME在数据库中创建了一个列,但是我想创建一个DATE列。

[DataType(DataType.Date)]
[DisplayFormatAttribute(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
public DateTime ReportDate { get; set; }

DATE在创建表期间如何创建类型为的列?

Answers:


22

大卫·罗斯的EF6版本的答案如下:

public class DataTypePropertyAttributeConvention 
    : PrimitivePropertyAttributeConfigurationConvention<DataTypeAttribute>
{
    public override void Apply(ConventionPrimitivePropertyConfiguration configuration, 
        DataTypeAttribute attribute)
    {
        if (attribute.DataType == DataType.Date)
        {
            configuration.HasColumnType("Date");
        }
    }
}

像以前一样注册:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Conventions.Add(new DataTypePropertyAttributeConvention());
}

这与Tyler Durden的方法具有相同的结果,除了它使用EF基类进行工作。


164

尝试使用ColumnAttributefrom System.ComponentModel.DataAnnotations(在EntityFramework.dll中定义):

[Column(TypeName="Date")]
public DateTime ReportDate { get; set; }

1
Sequence contains no matching element如果您指向的数据库不支持日期,则可能会出错。SQL Server 2014可以。
杰西

8
using System.ComponentModel.DataAnnotations.Schema;
EF6中,

10

我使用以下

    [DataType(DataType.Time)]
    public TimeSpan StartTime { get; set; }

    [DataType(DataType.Time)]
    public TimeSpan EndTime { get; set; }

    [DataType(DataType.Date)]
    [Column(TypeName = "Date")]
    public DateTime StartDate { get; set; }

    [DataType(DataType.Date)]
    [Column(TypeName = "Date")]
    public DateTime EndDate { get; set; }

使用Entity Framework 6和SQL Server Express 2012-11.0.2100.60(X64)。它可以完美运行并在SQL Server中生成时间/日期列类型


您的解决方案有效。@YakoobHammouri的无效。我必须同时使用注释[DataType(DataType.Date)][Column(TypeName = "Date")]您的建议。但是此解决方案创建日期格式为yyyy-mm-dd而不是MM-dd-yyyy
nam

9

我发现它在EF6中很好用。

我创建了一个约定来指定我的数据类型。此约定将数据库创建中的默认DateTime数据类型从datetime更改为datetime2。然后,它将更具体的规则应用于我用DataType(DataType.Date)属性修饰的任何属性。

public class DateConvention : Convention
{
    public DateConvention()
    {
        this.Properties<DateTime>()
            .Configure(c => c.HasColumnType("datetime2").HasPrecision(3));

        this.Properties<DateTime>()
            .Where(x => x.GetCustomAttributes(false).OfType<DataTypeAttribute>()
            .Any(a => a.DataType == DataType.Date))
            .Configure(c => c.HasColumnType("date"));
    }
}

然后在您的上下文中注册然后约定:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    modelBuilder.Conventions.Add(new DateConvention());
    // Additional configuration....
}

将属性添加到希望仅作为日期的任何DateTime属性中:

public class Participant : EntityBase
{
    public int ID { get; set; }

    [Required]
    [Display(Name = "Given Name")]
    public string GivenName { get; set; }

    [Required]
    [Display(Name = "Surname")]
    public string Surname { get; set; }

    [DataType(DataType.Date)]
    [Display(Name = "Date of Birth")]
    public DateTime DateOfBirth { get; set; }
}

1
真的很棒的解决方案!我想添加一件事要完全清楚,为了使用它,您需要在date属性上添加属性,例如[DataType(DataType.Date)] public DateTime IssueDate {get; 组; }
Stephen Lautier 2014年

@StephenLautier是的,如果希望仅将其用于特定的DateTime属性,则必须添加该属性。在我添加的代码中,我表明您还可以对所有DateTime类型应用通用规则,然后对具有DataType(DataType.Date)装饰的规则应用更具体的规则。希望这能消除任何混乱。
泰勒·德登

1
好的解决方案,但是EF确实提供了基类来为您完成这项工作-有关详细信息,请参见我的解决方案。
理查德

@Richard我赞成您的解决方案,因为您是正确的。我创建解决方案的原因是因为EF默认使用SQL Server中的datetime数据类型的DateTime属性,而不是与.NET DateTime属性兼容的datetime2数据类型。幸运的是,EF核心现已解决此问题。
泰勒·杜顿

5

如果你不喜欢与属性装饰你的类,你可以在此设置DbContextOnModelCreating是这样的:

public class DatabaseContext: DbContext
{
    // DbSet's

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // magic starts
        modelBuilder.Entity<YourEntity>()
                    .Property(e => e.ReportDate)
                    .HasColumnType("date");
        // magic ends

        // ... other bindings
    }
}

4

除了使用之外,ColumnAttribute您还可以为创建一个自定义属性约定DataTypeAttribute

public class DataTypePropertyAttributeConvention : AttributeConfigurationConvention<PropertyInfo, PrimitivePropertyConfiguration, DataTypeAttribute>
{
    public override void Apply(PropertyInfo memberInfo, PrimitivePropertyConfiguration configuration, DataTypeAttribute attribute)
    {
        if (attribute.DataType == DataType.Date)
        {
            configuration.ColumnType = "Date";
        }
    }
}

只需在您的OnModelCreating方法中注册约定:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Conventions.Add(new DataTypePropertyAttributeConvention());
}

这应该内置到EF中。感谢分享!
tugberk

不幸的是,自EF6起已弃用该标签,并且不再有效。
泰勒·德登

1
EF6确实提供了一种新的方法-有关详细信息,请参阅我的解决方案。
理查德(Richard)

3

这只是@LadislavMrnka对这个问题最投票的答案的增强

如果您有很多Date列,则可以创建自定义属性,然后在需要时使用它,这将在Entity类中产生更清晰的代码

public class DateColumnAttribute : ColumnAttribute
{
    public DateColumnAttribute()
    {
        TypeName = "date";
    }
}

用法

[DateColumn]
public DateTime DateProperty { get; set; }

-3

使用的最佳方式

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

但您必须使用 EntityFramework v 6.1.1

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.