Thực thể Khung Mã Ngày tạo trường Ngày đầu tiên


82

Tôi đang sử dụng phương pháp Entity Framework Code First để tạo bảng cơ sở dữ liệu của mình. Đoạn mã sau tạo một DATETIMEcột trong cơ sở dữ liệu, nhưng tôi muốn tạo một DATEcột.

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

Làm cách nào để tạo một loại cột DATEtrong khi tạo bảng?

Câu trả lời:


22

Phiên bản EF6 của câu trả lời của David Roth như sau:

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

Đăng ký cái này như trước:

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

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

Điều này có cùng kết quả với cách tiếp cận của Tyler Durden, ngoại trừ việc nó sử dụng lớp cơ sở EF cho công việc.


164

Cố gắng sử dụng ColumnAttributefrom System.ComponentModel.DataAnnotations(được định nghĩa trong EntityFramework.dll):

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

1
Bạn có thể gặp lỗi, Sequence contains no matching elementnếu bạn đang trỏ vào một DB không hỗ trợ ngày tháng. SQL Server 2014 không.
Jess

8
Trong EF6 bạn cầnusing System.ComponentModel.DataAnnotations.Schema;
JohnnyHK

10

Tôi sử dụng sau

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

Với Entity Framework 6 & SQL Server Express 2012 - 11.0.2100.60 (X64). Nó hoạt động hoàn hảo và tạo ra các loại cột thời gian / ngày trong máy chủ sql


Giải pháp của bạn đã hiệu quả. @YakoobHammouriđã không hoạt động. Tôi đã phải sử dụng cả chú thích [DataType(DataType.Date)][Column(TypeName = "Date")]như bạn đề xuất. Tuy nhiên giải pháp tạo ra định dạng ngày này như yyyy-mm-ddlà trái ngược vớiMM-dd-yyyy
nam

9

Tôi thấy điều này hoạt động tốt trong EF6.

Tôi đã tạo một quy ước để chỉ định kiểu dữ liệu của mình. Quy ước này thay đổi kiểu dữ liệu DateTime mặc định trong việc tạo cơ sở dữ liệu từ datetime thành datetime2. Sau đó, nó áp dụng một quy tắc cụ thể hơn cho bất kỳ thuộc tính nào mà tôi đã trang trí bằng thuộc tính 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"));
    }
}

Sau đó đăng ký rồi quy ước trong ngữ cảnh của bạn:

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

Thêm thuộc tính vào bất kỳ thuộc tính DateTime nào mà bạn chỉ muốn là ngày:

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
Giải pháp thực sự tuyệt vời! Một điều tôi muốn thêm vào để hoàn toàn rõ ràng, rằng để sử dụng điều này, bạn cần phải thêm thuộc tính vào thuộc tính ngày, ví dụ [DataType (DataType.Date)] public DateTime IssueDate {get; bộ; }
Stephen Lautier

@StephenLautier vâng bạn phải thêm thuộc tính nếu bạn muốn chỉ có thể sử dụng thuộc tính này cho các thuộc tính DateTime cụ thể. Trong đoạn mã tôi đã thêm, tôi cho thấy rằng bạn cũng có thể áp dụng quy tắc chung cho tất cả các loại DateTime của mình và sau đó là một quy tắc cụ thể hơn cho những loại có trang trí DataType (DataType.Date). Hy vọng điều này làm rõ ràng bất kỳ sự nhầm lẫn nào.
Tyler Durden

1
Giải pháp tốt, nhưng EF có cung cấp một lớp cơ sở để thực hiện công việc này cho bạn - hãy xem giải pháp của tôi để biết chi tiết.
Richard

@Richard Tôi đã bỏ phiếu cho giải pháp của bạn, vì bạn đã đúng. Tuy nhiên, lý do tôi tạo giải pháp của mình là vì EF mặc định các thuộc tính DateTime để sử dụng kiểu dữ liệu datetime trong SQL Server, chứ không phải kiểu dữ liệu datetime2 tương thích với thuộc tính .NET DateTime. Rất may, lõi EF đã khắc phục sự cố này ngay bây giờ.
Tyler Durden

5

Nếu bạn không muốn trang trí lớp học của bạn với các thuộc tính, bạn có thể thiết lập này trong DbContext's OnModelCreatingnhư thế này:

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

Bên cạnh việc sử dụng, ColumnAttributebạn cũng có thể tạo quy ước thuộc tính tùy chỉnh cho 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";
        }
    }
}

Chỉ cần đăng ký quy ước trong phương thức OnModelCreating của bạn:

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

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

Điều này nên được tích hợp vào EF. Cám ơn vì đã chia sẻ!
tugberk

Rất tiếc, tính năng này đã không được chấp nhận kể từ EF6 và không còn hợp lệ.
Tyler Durden,

1
EF6 đã cung cấp một cách mới để thực hiện việc này - hãy xem giải pháp của tôi để biết chi tiết.
Richard

3

Đây chỉ là phần nâng cao cho câu trả lời được bình chọn nhiều nhất bởi @LadislavMrnka cho câu hỏi này

nếu bạn có nhiều Datecột, thì bạn có thể tạo thuộc tính tùy chỉnh và sau đó sử dụng nó bất cứ khi nào bạn muốn, điều này sẽ tạo ra nhiều mã rõ ràng hơn trong các lớp Thực thể

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

Sử dụng

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

-3

cách tốt nhất nó sử dụng

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

nhưng bạn phải sử dụng EntityFramework v 6.1.1

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.