Erstellung des Felds für das erste Datum des Entity Framework-Codes

82

Ich verwende die Entity Framework Code First-Methode, um meine Datenbanktabelle zu erstellen. Der folgende Code erstellt eine DATETIMESpalte in der Datenbank, aber ich möchte eine DATESpalte erstellen .

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

Wie kann ich DATEwährend der Tabellenerstellung eine Spalte vom Typ erstellen ?

sfgroups
quelle

Antworten:

22

Die EF6-Version von David Roths Antwort lautet wie folgt:

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

Registrieren Sie dies wie zuvor:

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

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

Dies hat das gleiche Ergebnis wie Tyler Durdens Ansatz, außer dass eine EF-Basisklasse für den Job verwendet wird.

Richard
quelle
164

Versuchen Sie , verwenden ColumnAttributeaus System.ComponentModel.DataAnnotations(definiert in EntityFramework.dll):

[Column(TypeName="Date")]
public DateTime ReportDate { get; set; }
Ladislav Mrnka
quelle
1
Möglicherweise wird eine Fehlermeldung angezeigt Sequence contains no matching element, wenn Sie auf eine Datenbank zeigen, die das Datum nicht unterstützt. SQL Server 2014 funktioniert.
Jess
8
In EF6 brauchen Sieusing System.ComponentModel.DataAnnotations.Schema;
JohnnyHK
10

Ich benutze folgendes

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

Mit Entity Framework 6 und SQL Server Express 2012 - 11.0.2100.60 (X64). Es funktioniert perfekt und generiert Zeit- / Datumsspaltentypen in SQL Server

Irfan Ashraf
quelle
Ihre Lösung hat funktioniert. @YakoobHammourihat nicht funktioniert. Ich musste beide Anmerkungen verwenden [DataType(DataType.Date)]und [Column(TypeName = "Date")]wie Sie vorgeschlagen haben. Diese Lösung erstellte jedoch ein Datumsformat yyyy-mm-ddim Gegensatz zuMM-dd-yyyy
nam
9

Ich fand das funktioniert in EF6 gut.

Ich habe eine Konvention zum Festlegen meiner Datentypen erstellt. Diese Konvention ändert den Standard-DateTime-Datentyp bei der Datenbankerstellung von datetime in datetime2. Anschließend wird eine spezifischere Regel auf alle Eigenschaften angewendet, die ich mit dem Attribut DataType (DataType.Date) dekoriert habe.

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"));
    }
}

Dann registrieren Sie dann Konvention in Ihrem Kontext:

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

Fügen Sie das Attribut allen DateTime-Eigenschaften hinzu, die nur Datum sein sollen:

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
quelle
1
Wirklich tolle Lösung! Eine Sache, die ich hinzufügen möchte, um ganz klar zu sein, dass Sie, um dies zu verwenden, das Attribut der Datumseigenschaft hinzufügen müssen, z. B. [DataType (DataType.Date)] public DateTime IssueDate {get; einstellen; }
Stephen Lautier
@StephenLautier Ja, Sie müssen das Attribut hinzufügen, wenn Sie dies nur für bestimmte DateTime-Eigenschaften verwenden möchten. In dem Code, den ich hinzugefügt habe, zeige ich, dass Sie auch eine allgemeine Regel auf alle Ihre DateTime-Typen und dann eine spezifischere Regel auf diejenigen mit der DataType-Dekoration (DataType.Date) anwenden können. Hoffe, das klärt Verwirrung.
Tyler Durden
1
Gute Lösung, aber EF bietet eine Basisklasse, um diesen Job für Sie zu erledigen - Einzelheiten finden Sie in meiner Lösung.
Richard
@ Richard Ich habe Ihre Lösung hochgestimmt, weil Sie richtig sind. Der Grund, warum ich meine Lösung erstellt habe, war, dass EF in den DateTime-Eigenschaften standardmäßig den Datetime-Datentyp in SQL Server verwendet, nicht den Datetime2-Datentyp, der mit der .NET DateTime-Eigenschaft kompatibel ist. Zum Glück hat EF Core dieses Problem jetzt behoben.
Tyler Durden
5

Wenn Sie nicht Ihre Klassen mit Attributen schmücken, können Sie diesen Satz in der oben DbContextist OnModelCreatingwie folgt aus :

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
quelle
4

Neben der Verwendung können ColumnAttributeSie auch eine benutzerdefinierte Attributkonvention für Folgendes erstellen 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";
        }
    }
}

Registrieren Sie einfach die Konvention in Ihrer OnModelCreating-Methode:

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

     modelBuilder.Conventions.Add(new DataTypePropertyAttributeConvention());
}
David Roth
quelle
Dies sollte in EF eingebaut werden. Danke für das Teilen!
Tugberk
Leider ist dies ab EF6 veraltet und nicht mehr gültig.
Tyler Durden
1
EF6 hat hierfür eine neue Möglichkeit bereitgestellt - Einzelheiten finden Sie in meiner Lösung.
Richard
3

Dies ist nur eine Verbesserung für die am besten bewertete Antwort von @LadislavMrnka auf diese Frage

Wenn Sie viele DateSpalten haben, können Sie ein benutzerdefiniertes Attribut erstellen und es dann verwenden, wann immer Sie möchten. Dadurch wird in den Entitätsklassen saubererer Code erzeugt

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

Verwendung

[DateColumn]
public DateTime DateProperty { get; set; }
Hakan Fıstık
quelle
-3

der beste Weg es mit The

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

Sie müssen jedoch EntityFramework v 6.1.1 verwenden

Yakoob Hammouri
quelle