Typy entit

Zahrnutí sady DbSet typu do kontextu znamená, že je součástí modelu EF Core; Obvykle na takový typ odkazujeme jako na entitu. EF Core může číst a zapisovat instance entit z databáze nebo do databáze a pokud používáte relační databázi, EF Core může vytvářet tabulky pro vaše entity prostřednictvím migrací.

Zahrnutí typů do modelu

Podle konvence jsou typy vystavené ve vlastnostech DbSet ve vašem kontextu zahrnuty do modelu jako entity. Zahrnuté jsou také typy entit, které jsou zadané v OnModelCreating metodě, stejně jako všechny typy nalezené rekurzivním zkoumáním navigačních vlastností jiných zjištěných typů entit.

V ukázce kódu níže jsou zahrnuty všechny typy:

  • Blog je zahrnuta, protože je zpřístupněna ve vlastnosti DbSet v kontextu.
  • Post je zahrnuta, protože je zjištěna prostřednictvím Blog.Posts navigační vlastnosti.
  • AuditEntry vzhledem k tomu, že je zadán v OnModelCreating.
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; }
}

Vyloučení typů z modelu

Pokud nechcete, aby byl typ součástí modelu, můžete ho vyloučit:

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

Vyloučení z migrací

Poznámka

Možnost vyloučit tabulky z migrací byla zavedena v EF Core 5.0.

Někdy je užitečné mít stejný typ entity namapovaný ve více DbContext typech. To platí zejména při použití ohraničených kontextů, pro které je běžné mít pro každý ohraničený kontext jiný DbContext typ.

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

Při této migraci konfigurace se tabulka nevytvoří AspNetUsers , ale IdentityUser je stále součástí modelu a dá se použít normálně.

Pokud potřebujete tabulku znovu spravovat pomocí migrací, měla by se vytvořit nová migrace, kde AspNetUsers není vyloučena. Další migrace teď bude obsahovat všechny změny provedené v tabulce.

Název tabulky

Podle konvence se každý typ entity nastaví tak, aby mapoval na tabulku databáze se stejným názvem jako vlastnost DbSet, která zpřístupňuje entitu. Pokud pro danou entitu neexistuje žádná sada DbSet, použije se název třídy.

Název tabulky můžete nakonfigurovat ručně:

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

Schéma tabulky

Při použití relační databáze se tabulky vytvářejí podle konvence vytvořené ve výchozím schématu vaší databáze. Například Microsoft SQL Server použije dbo schéma (SQLite nepodporuje schémata).

Tabulky můžete nakonfigurovat tak, aby se vytvořily v určitém schématu následujícím způsobem:

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

Místo určení schématu pro každou tabulku můžete také definovat výchozí schéma na úrovni modelu pomocí rozhraní FLUENT API:

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

Všimněte si, že nastavení výchozího schématu ovlivní také další databázové objekty, jako jsou sekvence.

Zobrazení mapování

Typy entit lze mapovat na zobrazení databáze pomocí rozhraní API Fluent.

Poznámka

Ef předpokládá, že odkazované zobrazení již v databázi existuje, nevytvoří ho automaticky při migraci.

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

Mapování na zobrazení odebere výchozí mapování tabulky, ale počínaje ef 5.0 lze typ entity také namapovat na tabulku explicitně. V takovém případě se mapování dotazů použije pro dotazy a mapování tabulek se použije k aktualizacím.

Tip

Pokud chcete otestovat typy entit bez klíčů namapované na zobrazení pomocí zprostředkovatele v paměti, namapujte je na dotaz prostřednictvím ToInMemoryQuery. Další informace najdete v dokumentaci k poskytovateli paměti .

Mapování funkcí s hodnotou tabulky

Je možné mapovat typ entity na funkci s hodnotou tabulky (TVF) místo tabulky v databázi. Abychom to mohli ilustrovat, nadefinujme jinou entitu, která představuje blog s více příspěvky. V tomto příkladu je entita bez klíče, ale nemusí být.

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

Dále vytvořte následující funkci s hodnotou tabulky v databázi, která vrací pouze blogy s více příspěvky a počet příspěvků přidružených k jednotlivým blogům:

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
)

Entitu BlogWithMultiplePosts teď můžete namapovat na tuto funkci následujícím způsobem:

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

Poznámka

Aby bylo možné namapovat entitu na funkci s hodnotou tabulky, musí být funkce bez parametrů.

Obvykle se vlastnosti entity mapují na odpovídající sloupce vrácené TVF. Pokud sloupce vrácené TVF mají jiné názvy než vlastnost entity, pak je možné sloupce entity nakonfigurovat pomocí HasColumnName metody, stejně jako při mapování na běžnou tabulku.

Když je typ entity namapován na funkci s hodnotou tabulky, dotaz:

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

Vytvoří následující SQL:

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

Komentáře k tabulce

Můžete nastavit libovolný textový komentář, který se nastaví v databázové tabulce, což vám umožní dokumentovat schéma v databázi:

Poznámka

Nastavení komentářů prostřednictvím datových poznámek bylo zavedeno v EF Core 5.0.

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

Typy entit sdíleného typu

Poznámka

Podpora typů entit sdíleného typu byla zavedena v EF Core 5.0.

Typy entit, které používají stejný typ CLR, se označují jako typy entit sdíleného typu. Tyto typy entit musí být nakonfigurovány s jedinečným názvem, který musí být zadán při každém použití typu entity sdíleného typu kromě typu CLR. To znamená, že odpovídající DbSet vlastnost musí být implementována Set pomocí volání.

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