備註
這項功能已新增在查詢類型的名稱下。 後來更名為無索引鍵實體類型。
除了一般實體類型之外,EF Core 模型還可以包含 無索引鍵實體類型,可用來對不包含索引鍵值的數據執行資料庫查詢。
定義無索引鍵實體類型
無索引鍵實體類型可以定義如下:
[Keyless]
public class BlogPostsCount
{
public string BlogName { get; set; }
public int PostCount { get; set; }
}
無鍵實體類型的特性
無鍵實體類型支援許多與一般實體類型相同的映射功能,例如繼承映射和導覽屬性。 在關係型存放區上,他們可以透過 Fluent API 方法或數據批注來設定目標資料庫物件和數據行。
不過,它們與一般實體類型不同,因為它們:
- 無法定義索引鍵。
- 永遠不會追蹤 DbContext 中的變更,因此永遠不會在資料庫上插入、更新或刪除。
- 絕不會依慣例被發現。
- 僅支援導航對應功能的子集,特別是:
- 他們可能永遠不會充當關係的主要結尾。
- 他們可能沒有通往擁有的實體的導航功能
- 它們只能包含指向一般實體的參考導覽屬性。
- 實體不可含有無鍵實體類型的導覽屬性。
- 必須配置為
[Keyless]
數據批註或.HasNoKey()
方法呼叫。 - 可能對應至 定義查詢。 定義查詢是在模型中宣告的查詢,做為無索引鍵實體類型的數據源。
- 可以有階層,但必須對應為 TPH。
- 無法使用數據表分割或實體分割。
使用場景
無索引鍵實體類型的一些主要使用案例如下:
- 作為 SQL 查詢的傳回型別。
- 映射到不含主鍵的資料庫視圖。
- 映射至沒有定義主鍵的數據表。
- 對應至模型中定義的查詢。
對應至資料庫物件
使用 ToTable
或 ToView
Fluent API,將無索引鍵實體類型對應至資料庫物件。 從EF Core 的觀點來看,此方法中指定的資料庫對像是 檢視,這表示它會被視為只讀查詢來源,而且不能是更新、插入或刪除作業的目標。 不過,這並不表示資料庫物件實際上需要是資料庫檢視。 它也可以是將視為唯讀的資料庫數據表。 相反地,針對一般實體類型,EF Core 會假設方法中指定的 ToTable
資料庫物件可以視為 數據表,這表示它可以當做查詢來源使用,但也以更新、刪除和插入作業為目標。 事實上,您可以在 中 ToTable
指定資料庫檢視的名稱,只要檢視設定為可在資料庫上更新,所有專案都應該正常運作。
範例
下列範例示範如何使用無索引鍵實體類型來查詢資料庫檢視。
小提示
您可以在 GitHub 上檢視本文 範例。
首先,我們會定義簡單的部落格和文章模型:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
}
接下來,我們會定義簡單的資料庫檢視,以讓我們查詢與每個部落格相關聯的文章數目:
await db.Database.ExecuteSqlRawAsync(
@"CREATE VIEW View_BlogPostCounts AS
SELECT b.Name, Count(p.PostId) as PostCount
FROM Blogs b
JOIN Posts p on p.BlogId = b.BlogId
GROUP BY b.Name");
接下來,我們會定義類別來保存資料庫檢視的結果:
public class BlogPostsCount
{
public string BlogName { get; set; }
public int PostCount { get; set; }
}
接下來,我們會使用 API 在 HasNoKey
中設定無索引鍵實體類型。
我們使用 Fluent 配置 API 來設定無鍵實體類型的對應:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<BlogPostsCount>(
eb =>
{
eb.HasNoKey();
eb.ToView("View_BlogPostCounts");
eb.Property(v => v.BlogName).HasColumnName("Name");
});
}
接下來,我們會將 設定 DbContext
為 包含 DbSet<T>
:
public DbSet<BlogPostsCount> BlogPostCounts { get; set; }
最後,我們可以以標準方式查詢資料庫檢視:
var postCounts = await db.BlogPostCounts.ToListAsync();
foreach (var postCount in postCounts)
{
Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
Console.WriteLine();
}
小提示
請注意,我們也定義了內容層級查詢屬性 (DbSet),以作為針對此類型之查詢的根目錄。
小提示
若要使用記憶體內部提供者測試對應至檢視的無索引鍵實體類型,請透過 ToInMemoryQuery將其對應至查詢。 如需詳細資訊,請參閱 記憶體內提供者文件 。