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ímBlog.Posts
navigační vlastnosti.AuditEntry
vzhledem k tomu, že je zadán vOnModelCreating
.
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");
});
}
}