無索引鍵實體類型

注意

這項功能是在查詢類型的名稱下加入。 稍後會將它重新命名為無索引鍵的實體類型。 [Keyless]資料批註在 EFCore 5.0 中變成可供使用。

除了一般實體類型之外,EF Core 模型也可以包含 無索引鍵的實體類型,可用來針對不包含索引鍵值的資料執行資料庫查詢。

定義無索引鍵實體類型

您可以使用資料批註或 Fluent API 來定義無索引鍵實體類型:

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

無索引鍵實體類型特性

無索引鍵實體類型支援許多與一般實體類型相同的對應功能,例如繼承對應和導覽屬性。 在關聯式存放區上,他們可以透過流暢的 API 方法或資料批註來設定目標資料庫物件和資料行。

不過,它們與一般實體類型不同,因為它們:

  • 無法定義索引鍵。
  • 永遠不會追蹤 DbCoNtext 中的變更,因此永遠不會在資料庫中插入、更新或刪除。
  • 慣例不會探索到。
  • 只支援一組流覽對應功能,特別是:
    • 它們絕對不能做為關聯性的主要端點。
    • 他們可能沒有擁有實體的導覽
    • 它們只能包含指向一般實體的參考導覽屬性。
    • 實體不能包含無索引鍵實體類型的導覽屬性。
  • 需要使用 [Keyless] 資料批註或 .HasNoKey() 方法呼叫來設定。
  • 可能對應至 定義查詢。 定義查詢是在模型中宣告的查詢,可作為無索引鍵實體類型的資料來源。

使用方式情節

無索引鍵實體類型的部分主要使用案例如下:

  • 做為原始 SQL 查詢的傳回型別。
  • 對應至不含主鍵的資料庫 views。
  • 對應至未定義主鍵的資料表。
  • 對應至模型中定義的查詢。

對應至資料庫物件

使用或流暢的 API 即可將無索引鍵實體類型對應至資料庫 ToTable 物件 ToView 。 從 EF Core 的觀點來看,這個方法中所指定的資料庫物件是一個 視圖,這表示它會被視為唯讀查詢來源,而不能是 update、insert 或 delete 作業的目標。 但是,這並不表示資料庫物件實際上必須是資料庫的視圖。 它也可以是將被視為唯讀的資料庫資料表。 相反地,對於一般的實體類型,EF Core 會假設在方法中指定的資料庫物件 ToTable 可以視為 ToTable,這表示它可以當做查詢來源使用,也可作為 update、delete 和 insert 作業的目標。 事實上,您可以在中指定資料庫的名稱 ToTable ,而且只要視圖設定為可在資料庫上更新,一切都應可正常運作。

注意

在 EF Core 5.0 ToView 假設物件已經存在於資料庫中,而且不是由遷移所建立。 在 EF Core 5.0 和更新版本中 modelBuilder.Entity<ViewType>().ToTable("ViewNameInDatabase", t => t.ExcludeFromMigrations()) ,若要將物件從遷移中排除,請參閱 modelBuilder.Entity<ViewType>().ToTable("ViewNameInDatabase", t => t.ExcludeFromMigrations())

範例

下列範例示範如何使用無索引鍵的實體類型來查詢資料庫檢視。

提示

您可以在 GitHub 上檢視此文章的範例 \(英文\)。

首先,我們會定義簡單的 Blog 和 Post 模型:

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

接下來,我們會定義一個簡單的資料庫檢視,讓我們查詢與每個 blog 相關聯的貼文數目:

db.Database.ExecuteSqlRaw(
    @"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 在 OnModelCreating 中設定無索引鍵實體類型 。 我們會使用流暢的設定 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 = db.BlogPostCounts.ToList();

foreach (var postCount in postCounts)
{
    Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
    Console.WriteLine();
}

提示

請注意,我們也定義了內容層級查詢屬性 (DbSet) 做為針對此型別進行查詢的根。

提示

若要使用記憶體內部提供者來測試對應至 views 的無索引鍵實體型別,請透過將它們對應至查詢 ToInMemoryQuery 。 如需詳細資訊,請參閱使用此技術的可執行 範例