Tworzenie pola Entity Framework Code First Date

83

Do tworzenia tabeli bazy danych używam metody Entity Framework Code First. Poniższy kod tworzy DATETIMEkolumnę w bazie danych, ale chcę utworzyć DATEkolumnę.

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

Jak mogę utworzyć kolumnę typu DATEpodczas tworzenia tabeli?

sfgroups
źródło

Odpowiedzi:

22

Wersja EF6 odpowiedzi Davida Rotha jest następująca:

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

Zarejestruj to jak poprzednio:

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

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

Daje to ten sam wynik, co podejście Tylera Durdena, z tą różnicą, że do zadania używa klasy bazowej EF.

Richard
źródło
165

Spróbuj użyć ColumnAttributefrom System.ComponentModel.DataAnnotations(zdefiniowanego w EntityFramework.dll):

[Column(TypeName="Date")]
public DateTime ReportDate { get; set; }
Ladislav Mrnka
źródło
1
Możesz otrzymać błąd, Sequence contains no matching elementjeśli wskazujesz bazę danych, która nie obsługuje daty. SQL Server 2014 tak.
Jess
8
W using System.ComponentModel.DataAnnotations.Schema;
EF6
11

Używam następujących

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

Z Entity Framework 6 i SQL Server Express 2012 - 11.0.2100.60 (X64). Działa doskonale i generuje typy kolumn czasu / daty na serwerze sql

Irfan Ashraf
źródło
Twoje rozwiązanie zadziałało. @YakoobHammourinie działa. Musiałem użyć zarówno adnotacji, jak [DataType(DataType.Date)]i [Column(TypeName = "Date")]sugerowałeś. Jednak to rozwiązanie stworzyło format daty yyyy-mm-ddw przeciwieństwie doMM-dd-yyyy
nam
9

Uważam, że to działa ładnie w EF6.

Stworzyłem konwencję określania moich typów danych. Ta konwencja zmienia domyślny typ danych DateTime podczas tworzenia bazy danych z datetime na datetime2. Następnie stosuje bardziej szczegółową regułę do wszystkich właściwości, które ozdobiłem atrybutem 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"));
    }
}

Następnie zarejestruj się, a następnie konwencja w swoim kontekście:

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

Dodaj atrybut do wszystkich właściwości DateTime, które mają być tylko datą:

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; }
}
Tyler Durden
źródło
1
Naprawdę świetne rozwiązanie! Jedna rzecz, którą chcę dodać, aby była całkowicie jasna, że ​​aby z niej skorzystać, należy dodać atrybut do właściwości daty, np. [DataType (DataType.Date)] public DateTime IssueDate {get; zestaw; }
Stephen Lautier
@StephenLautier tak, musisz dodać atrybut, jeśli chcesz mieć możliwość używania go tylko dla określonych właściwości DateTime. W kodzie, który dodałem, pokazuję, że możesz również zastosować ogólną regułę do wszystkich swoich typów DateTime, a następnie bardziej szczegółową regułę do tych z dekoracją DataType (DataType.Date). Mam nadzieję, że to wyjaśni wszelkie nieporozumienia.
Tyler Durden,
1
Dobre rozwiązanie, ale EF zapewnia klasę bazową do wykonania tego zadania za Ciebie - zobacz moje rozwiązanie po szczegóły.
Richard
@Richard Głosowałem za twoim rozwiązaniem, ponieważ masz rację. Powodem, dla którego stworzyłem moje rozwiązanie, było jednak to, że EF domyślnie ustawia właściwości DateTime, aby używać typu danych datetime w SQL Server, a nie typu danych datetime2, który jest zgodny z właściwością DateTime platformy .NET. Na szczęście rdzeń EF rozwiązał ten problem teraz.
Tyler Durden
5

Jeśli nie chcesz ozdobić swoje zajęcia z atrybutów, można to ustawić w DbContext„s OnModelCreatingjak to:

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
    }
}
Stoyan Dimov
źródło
4

Oprócz używania ColumnAttributemożesz również utworzyć konwencję atrybutów niestandardowych dla 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";
        }
    }
}

Po prostu zarejestruj konwencję w swojej metodzie OnModelCreating:

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

     modelBuilder.Conventions.Add(new DataTypePropertyAttributeConvention());
}
David Roth
źródło
Powinno to być wbudowane w EF. Dzięki za udostępnienie!
tugberk
Niestety od wersji EF6 jest to przestarzałe i nie jest już ważne.
Tyler Durden
1
EF6 zapewnił nowy sposób zrobienia tego - zobacz moje rozwiązanie, aby uzyskać szczegółowe informacje.
Richard
3

To tylko ulepszenie najbardziej pozytywnej odpowiedzi udzielonej przez @LadislavMrnka na to pytanie

jeśli masz wiele Datekolumn, możesz utworzyć atrybut niestandardowy, a następnie użyć go, kiedy chcesz, spowoduje to bardziej przejrzysty kod w klasach Entity

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

Stosowanie

[DateColumn]
public DateTime DateProperty { get; set; }
Hakan Fıstık
źródło
-3

najlepszy sposób przy użyciu

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

ale musisz użyć EntityFramework w wersji 6.1.1

Yakoob Hammouri
źródło