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

Posted

技术标签:

【中文标题】实体框架代码首次日期字段创建【英文标题】:Entity Framework Code First Date field creation 【发布时间】:2011-08-05 05:15:09 【问题描述】:

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

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

如何在创建表的过程中创建DATE 类型的列?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

如果您指向不支持日期的数据库,您可能会收到错误,Sequence contains no matching element。 SQL Server 2014 可以。 在 EF6 中你需要using System.ComponentModel.DataAnnotations.Schema;【参考方案2】:

大卫罗斯的答案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 基类来完成这项工作。

【讨论】:

【参考方案3】:

我使用以下

[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; 

使用实体框架 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【参考方案4】:

我发现这在 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; 

【讨论】:

非常棒的解决方案!我想添加的一件事是完全清楚的,为了使用它,您需要在 date 属性上添加属性,例如[DataType(DataType.Date)] public DateTime IssueDate get;放; @StephenLautier 是的,如果您希望仅将其用于特定的 DateTime 属性,则必须添加该属性。在我添加的代码中,我展示了您还可以将一般规则应用于所有 DateTime 类型,然后将更具体的规则应用于具有 DataType(DataType.Date) 装饰的那些。希望这可以消除任何困惑。 很好的解决方案,但 EF 确实提供了一个基类来为您完成这项工作 - 有关详细信息,请参阅我的解决方案。 @Richard 我对您的解决方案投了赞成票,因为您是正确的。我创建解决方案的原因是因为 EF 默认 DateTime 属性在 SQL Server 中使用 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
    

【讨论】:

【参考方案6】:

除了使用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 中。感谢分享! 不幸的是,从 EF6 开始,这已被弃用并且不再有效。 EF6 确实提供了一种新的方法 - 有关详细信息,请参阅我的解决方案。【参考方案7】:

这只是@LadislavMrnka 在这个问题上对most up-voted answer 的增强

如果您有很多 Date 列,那么您可以创建自定义属性,然后在需要时使用它,这将在实体类中生成更简洁的代码

public class DateColumnAttribute : ColumnAttribute

    public DateColumnAttribute()
    
        TypeName = "date";
    

用法

[DateColumn]
public DateTime DateProperty  get; set; 

【讨论】:

【参考方案8】:

这适用于 EF Core 5 + PostgreSQL:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class Birthday

    [Key]
    public int Id  get; set; 
    
    [Column(TypeName = "date")]
    public DateTime DateOfBirth  get; set; 


见column data types。

【讨论】:

【参考方案9】:

它使用的最佳方式

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

但您必须使用 EntityFramework v 6.1.1

【讨论】:

以上是关于实体框架代码首次日期字段创建的主要内容,如果未能解决你的问题,请参考以下文章

使用实体框架代码优先创建文本列[重复]

如何使用实体框架向数据库服务器询问当前日期时间?

实体框架代码优先和搜索标准

Hibernate/JPA - 使用@Future 更新还包含日期字段的实体字段

首次使用实体框架代码时将外键设置为 null

实体框架仅日期属性格式