Entitätseigenschaften

Jeder Entitätstyp in Ihrem Modell verfügt über eine Reihe von Eigenschaften, die EF Core aus der Datenbank liest und dort hinein schreibt. Wenn Sie eine relationale Datenbank verwenden, werden Entitätseigenschaften Tabellenspalten zugeordnet.

Eingeschlossene und ausgeschlossene Eigenschaften

Standardmäßig werden alle öffentlichen Eigenschaften mit einem Getter und einem Setter in das Modell eingeschlossen.

Bestimmte Eigenschaften können wie folgt ausgeschlossen werden:

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [NotMapped]
    public DateTime LoadedFromDatabase { get; set; }
}

Spaltennamen

Standardmäßig werden Entitätseigenschaften bei Verwendung einer relationalen Datenbank Tabellenspalten zugeordnet, die denselben Namen wie die Eigenschaft aufweisen.

Wenn Sie Ihre Spalten lieber mit unterschiedlichen Namen konfigurieren möchten, können Sie dies wie im folgenden Codeschnipsel tun:

public class Blog
{
    [Column("blog_id")]
    public int BlogId { get; set; }

    public string Url { get; set; }
}

Spaltendatentypen

Bei Verwendung einer relationalen Datenbank wählt der Datenbankanbieter einen Datentyp basierend auf dem .NET-Typ der Eigenschaft aus. Außerdem werden andere Metadaten berücksichtigt, z. B. die konfigurierte maximale Länge, ob die Eigenschaft Teil eines Primärschlüssels ist usw.

Beispielsweise ordnet SQL Server DateTime-Eigenschaften datetime2(7)-Spalten und string-Eigenschaften nvarchar(max)-Spalten zu (oder für Eigenschaften, die als Schlüssel verwendet werden, zu nvarchar(450)).

Sie können Ihre Spalten auch so konfigurieren, dass ein exakter Datentyp für eine Spalte angegeben wird. Der folgende Code konfiguriert z. B. Url als nicht-Unicode-Zeichenfolge mit maximaler Länge 200 und Rating als Dezimalzahl mit Genauigkeit 5 und Skalierung 2:

public class Blog
{
    public int BlogId { get; set; }

    [Column(TypeName = "varchar(200)")]
    public string Url { get; set; }

    [Column(TypeName = "decimal(5, 2)")]
    public decimal Rating { get; set; }
}

Maximale Länge

Das Konfigurieren einer maximalen Länge gibt dem Datenbankanbieter einen Hinweis auf den entsprechenden Spaltendatentyp, der für eine bestimmte Eigenschaft ausgewählt werden soll. Die maximale Länge gilt nur für Arraydatentypen wie string und byte[].

Hinweis

Entity Framework führt keine Überprüfung der maximalen Länge durch, bevor Daten an den Anbieter übergeben werden. Es ist Sache des Anbieters oder Datenspeichers, ggf. eine Überprüfung durchzuführen. Wenn Sie beispielsweise SQL Server als Ziel festlegen, führt die Überschreitung der maximalen Länge zu einer Ausnahme, da der Datentyp der zugrunde liegenden Spalte das Speichern übermäßiger Daten nicht zulässt.

Im folgenden Beispiel wird beim Konfigurieren einer maximalen Länge von 500 eine Spalte vom Typ nvarchar(500) auf SQL Server erstellt:

public class Blog
{
    public int BlogId { get; set; }

    [MaxLength(500)]
    public string Url { get; set; }
}

Genauigkeit und Skalierung

Einige relationale Datentypen unterstützen die Genauigkeits- und Skalierungsfacetten. Diese steuern, welche Werte gespeichert werden können, und wie viel Speicherplatz für die Spalte benötigt wird. Welche Datentypen Genauigkeit und Skalierung unterstützen, ist datenbankabhängig, aber in den meisten Datenbanken unterstützen die Typen decimal und DateTime diese Facetten nicht. Bei decimal-Eigenschaften definiert die Genauigkeit die maximale Anzahl von Ziffern, die zum Ausdrücken eines beliebigen Werts, den die Spalte enthält, erforderlich sind, und die Skalierung definiert die maximale Anzahl der benötigten Dezimalstellen. Bei DateTime-Eigenschaften definiert die Genauigkeit die maximale Anzahl von Ziffern, die zum Ausdrücken von Sekundenbruchteilen erforderlich sind, und die Skalierung wird nicht verwendet.

Hinweis

Entity Framework führt keine Überprüfung der Genauigkeit oder Skalierung durch, bevor Daten an den Anbieter übergeben werden. Es ist Sache des Anbieters oder Datenspeichers, ggf. eine Überprüfung durchzuführen. Beispielsweise lässt sich für eine Spalte vom Datentyp datetime unter SQL Server nicht die Genauigkeit einstellen, während datetime2 eine Genauigkeit zwischen 0 und 7 einschließlich haben kann.

Im folgenden Beispiel führt die Konfiguration der Score-Eigenschaft mit Genauigkeit 14 und Skalierung 2 dazu, dass eine Spalte vom Typ decimal(14,2) in SQL Server erstellt wird, und die Konfiguration der LastUpdated-Eigenschaft mit Genauigkeit 3 führt zu einer Spalte vom Typ datetime2(3):

public class Blog
{
    public int BlogId { get; set; }
    [Precision(14, 2)]
    public decimal Score { get; set; }
    [Precision(3)]
    public DateTime LastUpdated { get; set; }
}

Die Skalierung wird nie definiert, ohne zuerst die Genauigkeit zu definieren, sodass die Datenanmerkung zum Definieren der Skalierung [Precision(precision, scale)] lautet.

Unicode

In einigen relationalen Datenbanken sind unterschiedliche Typen vorhanden, um Unicode- und Nicht-Unicode-Textdaten darzustellen. In SQL Server wird nvarchar(x) z. B. verwendet, um Unicode-Daten in UTF-16 darzustellen, während varchar(x) zum Darstellen von Nicht-Unicode-Daten verwendet wird (siehe jedoch die Hinweise zur Unterstützung von SQL Server UTF-8). Für Datenbanken, die dieses Konzept nicht unterstützen, hat die Konfiguration keine Auswirkungen.

Texteigenschaften werden standardmäßig als Unicode konfiguriert. Sie können eine Spalte wie folgt als Nicht-Unicode konfigurieren:

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }

    [Unicode(false)]
    [MaxLength(22)]
    public string Isbn { get; set; }
}

Erforderliche und optionale Eigenschaften

Eine Eigenschaft wird als optional betrachtet, wenn es zulässig ist, dass sie null enthält. Wenn null kein gültiger Wert ist, der einer Eigenschaft zugewiesen werden kann, wird es als erforderliche Eigenschaft betrachtet. Beim Zuordnen zu einem relationalen Datenbankschema werden erforderliche Eigenschaften als nicht Nullwerte zulassende und optionale Eigenschaften als Nullwerte zulassende Spalten erstellt.

Konventionen

Standardmäßig wird eine Eigenschaft, deren .NET-Typ NULL enthalten kann, als optional konfiguriert, wohingegen Eigenschaften, deren .NET-Typ nicht NULL enthalten kann, als erforderlich konfiguriert werden. Beispielsweise werden alle Eigenschaften mit .NET-Werttypen (int, decimal, bool usw.) als erforderlich konfiguriert, und alle Eigenschaften mit Nullwerte zulassenden .NET-Werttypen (int?, decimal?, bool? usw.) werden als optional konfiguriert.

C# 8 hat ein neues Feature namens Nullwerte zulassende Verweistypen (Nullable Reference Types, NRT) eingeführt, mit dem Verweistypen mit Anmerkungen versehen werden können, um anzugeben, ob sie NULL enthalten können oder nicht. Dieses Feature ist in neuen Projektvorlagen standardmäßig aktiviert, bleibt aber in vorhandenen Projekten deaktiviert, sofern es nicht explizit aktiviert wird. Nullwerte zulassende Verweistypen wirken sich auf das Verhalten von EF Core wie folgt aus:

  • Wenn Nullwerte zulassende Verweistypen deaktiviert sind, werden alle Eigenschaften mit .NET-Verweistypen als optional gemäß Konvention konfiguriert (z. B string).
  • Wenn Nullwerte zulassende Verweistypen aktiviert sind, werden Eigenschaften auf der C#-NULL-Zulässigkeit ihres .NET-Typs basierend konfiguriert: string? wird als optional, aber string als erforderlich konfiguriert.

Das folgende Beispiel zeigt einen Entitätstyp mit erforderlichen und optionalen Eigenschaften, wobei das Nullverweisfeature deaktiviert und aktiviert ist:

public class CustomerWithoutNullableReferenceTypes
{
    public int Id { get; set; }

    [Required] // Data annotations needed to configure as required
    public string FirstName { get; set; }

    [Required] // Data annotations needed to configure as required
    public string LastName { get; set; }

    public string MiddleName { get; set; } // Optional by convention
}

Die Verwendung Nullwerte zulassende Verweistypen wird empfohlen, da sie die in C#-Code ausgedrückte NULL-Zulässigkeit in das Modell von EF Core und die Datenbank einfließen lässt und die Verwendung der Fluent-API oder Datenanmerkungen zum zweimaligen Ausdrücken desselben Konzepts vermeidet.

Hinweis

Aktivieren Sie Nullwerte zulassende Verweistypen für ein vorhandenes Projekt mit Vorsicht: Zuvor als optional konfigurierte Verweistypeigenschaften werden jetzt als erforderlich konfiguriert, es sei denn, sie werden explizit als Nullwerte zulassend gekennzeichnet. Beim Verwalten eines relationalen Datenbankschemas kann dies dazu führen, dass Migrationen generiert werden, die die NULL-Zulässigkeit der Datenbankspalte ändern.

Weitere Informationen zu Nullwerte zulassenden Verweistypen und deren Verwendung mit EF Core finden Sie auf der dedizierten Dokumentationsseite für dieses Feature.

Explizite Konfiguration

Eine Eigenschaft, die nach Konvention optional sein würde, kann wie folgt als erforderlich konfiguriert werden:

public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

Spaltensortierungen

Eine Sortierung kann für Textspalten definiert werden, die bestimmt, wie sie verglichen und geordnet werden. Mit dem folgenden Codeschnipsel wird beispielsweise eine SQL Server-Spalte so konfiguriert, dass die Groß-/Kleinschreibung nicht beachtet wird:

modelBuilder.Entity<Customer>().Property(c => c.Name)
    .UseCollation("SQL_Latin1_General_CP1_CI_AS");

Wenn für alle Spalten in einer Datenbank eine bestimmte Sortierung verwendet werden muss, definieren Sie stattdessen die Sortierung auf Datenbankebene.

Allgemeine Informationen zur EF Core-Unterstützung für Sortierungen finden Sie auf der Seite zur Sortierungsdokumentation.

Spaltenkommentare

Sie können einen beliebigen Textkommentar festlegen, der in der Datenbankspalte festgelegt wird, sodass Sie Ihr Schema in der Datenbank dokumentieren können:

public class Blog
{
    public int BlogId { get; set; }

    [Comment("The URL of the blog")]
    public string Url { get; set; }
}

Spaltenreihenfolge

Standardmäßig werden beim Erstellen einer Tabelle mit Migrationen zuerst Primärschlüsselspalten von EF Core sortiert, gefolgt von Eigenschaften des Entitätstyps und eigenen Typen und schließlich Eigenschaften aus Basistypen. Sie können jedoch eine andere Spaltenreihenfolge angeben:

public class EntityBase
{
    [Column(Order = 0)]
    public int Id { get; set; }
}

public class PersonBase : EntityBase
{
    [Column(Order = 1)]
    public string FirstName { get; set; }

    [Column(Order = 2)]
    public string LastName { get; set; }
}

public class Employee : PersonBase
{
    public string Department { get; set; }
    public decimal AnnualSalary { get; set; }
}

Mit der Fluent-API kann die durch Attribute festgelegte Reihenfolge überschrieben werden. Zudem lassen sich Konflikte lösen, bei denen Attribute für verschiedene Eigenschaften dieselbe Reihenfolgennummer angeben.

Beachten Sie, dass die meisten Datenbanken das Sortieren von Spalten nur beim Erstellen der Tabelle unterstützen. Dies bedeutet, dass das Attribut für die Spaltenreihenfolge nicht verwendet werden kann, um Spalten in einer vorhandenen Tabelle neu zu sortieren.