ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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


L
Ladislav Mrnka

尝试使用 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;
R
Richard

David Roth 回答的 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 基类来完成这项工作。


H
Hakan Fıstık

我使用以下

[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
T
Tyler Durden

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

真的很棒的解决方案!我想添加的一件事是完全清楚的,为了使用它,您需要在日期属性上添加属性,例如 [DataType(DataType.Date)] public DateTime IssueDate { get;放; }
@StephenLautier 是的,如果您希望仅将其用于特定的 DateTime 属性,则必须添加该属性。在我添加的代码中,我展示了您还可以将一般规则应用于所有 DateTime 类型,然后将更具体的规则应用于具有 DataType(DataType.Date) 装饰的那些。希望这可以消除任何困惑。
很好的解决方案,但 EF 确实提供了一个基类来为您完成这项工作 - 有关详细信息,请参阅我的解决方案。
@Richard 我对您的解决方案投了赞成票,因为您是正确的。我创建解决方案的原因是因为 EF 默认 DateTime 属性在 SQL Server 中使用 datetime 数据类型,而不是与 .NET DateTime 属性兼容的 datetime2 数据类型。值得庆幸的是,EF 核心现在已经解决了这个问题。
S
Stoyan Dimov

如果您不想用属性装饰您的类,您可以在 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
    }
}

D
David Roth

除了使用 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 确实提供了一种新的方法 - 有关详细信息,请参阅我的解决方案。
H
Hakan Fıstık

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

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

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

用法

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

A
Aleksei Mialkin

这适用于 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


H
Hakan Fıstık

它使用的最佳方式

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

但您必须使用 EntityFramework v 6.1.1