Entitätstypen

Wenn Sie ein DbSet eines Typs in Ihren Kontext einschließen, ist es im EF Core-Modell enthalten. in der Regel wird ein solcher Typ als Entität bezeichnet. EF Core kann Entitätsinstanzen aus der Datenbank lesen und in die Datenbank schreiben. Wenn Sie eine relationale Datenbank verwenden, kann EF Core Tabellen für Ihre Entitäten über Migrationen erstellen.

Einschließen von Typen in das Modell

Gemäß der Konvention werden Typen, die in DbSet-Eigenschaften in Ihrem Kontext verfügbar gemacht werden, als Entitäten in das Modell eingeschlossen. Entitätstypen, die in der OnModelCreating -Methode angegeben sind, sind ebenfalls enthalten, ebenso wie alle Typen, die durch rekursives Untersuchen der Navigationseigenschaften anderer ermittelter Entitätstypen gefunden werden.

Im folgenden Codebeispiel sind alle Typen enthalten:

  • Blog ist enthalten, da sie in einer DbSet-Eigenschaft im Kontext verfügbar gemacht wird.
  • Post ist enthalten, da sie über die Blog.Posts Navigationseigenschaft ermittelt wird.
  • AuditEntry da sie in OnModelCreatingangegeben ist.
internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AuditEntry>();
    }
}

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

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog { get; set; }
}

public class AuditEntry
{
    public int AuditEntryId { get; set; }
    public string Username { get; set; }
    public string Action { get; set; }
}

Ausschließen von Typen aus dem Modell

Wenn Sie keinen Typ in das Modell einbeziehen möchten, können Sie ihn ausschließen:

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

Ausschließen von Migrationen

Manchmal ist es hilfreich, denselben Entitätstyp in mehreren DbContext Typen zuzuordnen. Dies gilt insbesondere bei der Verwendung von kontextgebundenen Kontexten, für die es üblich ist, für jeden kontextgebundenen Kontext einen anderen DbContext Typ zu haben.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<IdentityUser>()
        .ToTable("AspNetUsers", t => t.ExcludeFromMigrations());
}

Mit dieser Konfiguration erstellen Migrationen nicht die AspNetUsers Tabelle, ist aber IdentityUser weiterhin im Modell enthalten und kann normal verwendet werden.

Wenn Sie erneut mit der Verwaltung der Tabelle mithilfe von Migrationen beginnen müssen, sollte eine neue Migration erstellt werden, bei der AspNetUsers nicht ausgeschlossen wird. Die nächste Migration enthält nun alle An der Tabelle vorgenommenen Änderungen.

Tabellenname

Gemäß der Konvention wird jeder Entitätstyp so eingerichtet, dass er einer Datenbanktabelle mit demselben Namen wie die DbSet-Eigenschaft zugeordnet wird, die die Entität verfügbar macht. Wenn für die angegebene Entität kein DbSet vorhanden ist, wird der Klassenname verwendet.

Sie können den Tabellennamen manuell konfigurieren:

[Table("blogs")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Tabellenschema

Wenn Sie eine relationale Datenbank verwenden, werden Tabellen gemäß der Konvention im Standardschema Ihrer Datenbank erstellt. Microsoft SQL Server verwendet beispielsweise das dbo Schema (SQLite unterstützt keine Schemas).

Sie können Tabellen so konfigurieren, dass sie in einem bestimmten Schema erstellt werden:

[Table("blogs", Schema = "blogging")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Anstatt das Schema für jede Tabelle anzugeben, können Sie das Standardschema auch auf Modellebene mit der Fluent-API definieren:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasDefaultSchema("blogging");
}

Beachten Sie, dass sich das Festlegen des Standardschemas auch auf andere Datenbankobjekte auswirkt, z. B. Sequenzen.

Zuordnung anzeigen

Entitätstypen können mithilfe der Fluent-API Datenbanksichten zugeordnet werden.

Hinweis

EF geht davon aus, dass die referenzierte Sicht bereits in der Datenbank vorhanden ist, und erstellt sie nicht automatisch in einer Migration.

modelBuilder.Entity<Blog>()
    .ToView("blogsView", schema: "blogging");

Durch die Zuordnung zu einer Ansicht wird die Standardtabellenzuordnung entfernt, aber der Entitätstyp kann auch explizit einer Tabelle zugeordnet werden. In diesem Fall wird die Abfragezuordnung für Abfragen und die Tabellenzuordnung für Updates verwendet.

Tipp

Um schlüssellose Entitätstypen, die Ansichten zugeordnet sind, mithilfe des In-Memory-Anbieters zu testen, ordnen Sie sie über ToInMemoryQueryeiner Abfrage zu. Weitere Informationen finden Sie in der Dokumentation zu In-Memory-Anbietern .

Tabellenwertfunktionszuordnung

Es ist möglich, einen Entitätstyp einer Tabellenwertfunktion (Table-Valued Function, TVF) anstelle einer Tabelle in der Datenbank zuzuordnen. Um dies zu veranschaulichen, definieren wir eine andere Entität, die den Blog mit mehreren Beiträgen darstellt. Im Beispiel ist die Entität schlüssellos, muss aber nicht sein.

public class BlogWithMultiplePosts
{
    public string Url { get; set; }
    public int PostCount { get; set; }
}

Erstellen Sie als Nächstes die folgende Tabellenwertfunktion in der Datenbank, die nur Blogs mit mehreren Beiträgen sowie die Anzahl der Beiträge zurückgibt, die jedem dieser Blogs zugeordnet sind:

CREATE FUNCTION dbo.BlogsWithMultiplePosts()
RETURNS TABLE
AS
RETURN
(
    SELECT b.Url, COUNT(p.BlogId) AS PostCount
    FROM Blogs AS b
    JOIN Posts AS p ON b.BlogId = p.BlogId
    GROUP BY b.BlogId, b.Url
    HAVING COUNT(p.BlogId) > 1
)

Nun kann die Entität BlogWithMultiplePosts dieser Funktion wie folgt zugeordnet werden:

modelBuilder.Entity<BlogWithMultiplePosts>().HasNoKey().ToFunction("BlogsWithMultiplePosts");

Hinweis

Um eine Entität einer Tabellenwertfunktion zuzuordnen, muss die Funktion parameterlos sein.

Üblicherweise werden die Entitätseigenschaften übereinstimmenden Spalten zugeordnet, die vom TVF zurückgegeben werden. Wenn die vom TVF zurückgegebenen Spalten andere Namen als die Entitätseigenschaft haben, können die Spalten der Entität mit der HasColumnName -Methode konfiguriert werden, genau wie bei der Zuordnung zu einer regulären Tabelle.

Wenn der Entitätstyp einer Tabellenwertfunktion zugeordnet ist, lautet die Abfrage:

var query = from b in context.Set<BlogWithMultiplePosts>()
            where b.PostCount > 3
            select new { b.Url, b.PostCount };

Dies generiert diese SQL-Anweisung:

SELECT [b].[Url], [b].[PostCount]
FROM [dbo].[BlogsWithMultiplePosts]() AS [b]
WHERE [b].[PostCount] > 3

Tabellenkommentare

Sie können einen beliebigen Textkommentar festlegen, der für die Datenbanktabelle festgelegt wird, sodass Sie Ihr Schema in der Datenbank dokumentieren können:

[Comment("Blogs managed on the website")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Entitätstypen vom Typ Shared

Entitätstypen, die den gleichen CLR-Typ verwenden, werden als Entitätstypen vom typ shared bezeichnet. Diese Entitätstypen müssen mit einem eindeutigen Namen konfiguriert werden, der immer dann bereitgestellt werden muss, wenn der Entitätstyp shared-type zusätzlich zum CLR-Typ verwendet wird. Dies bedeutet, dass die entsprechende DbSet Eigenschaft mithilfe eines Aufrufs Set implementiert werden muss.

internal class MyContext : DbContext
{
    public DbSet<Dictionary<string, object>> Blogs => Set<Dictionary<string, object>>("Blog");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.SharedTypeEntity<Dictionary<string, object>>(
            "Blog", bb =>
            {
                bb.Property<int>("BlogId");
                bb.Property<string>("Url");
                bb.Property<DateTime>("LastUpdated");
            });
    }
}