簡體   English   中英

Net Core:通用存儲庫主 ID 實體框架中的關鍵性能

[英]Net Core: Generic Repository Primary Id Key Performance in Entity Framework

我們正在審查通用存儲庫模式中的兩種不同方法。 目前,想要將主鍵映射到 Id。 這樣做的目的是映射到使用 Id 的通用存儲庫接口。 下面提供兩種解決方案。

.FindPrimaryKey().Properties 對性能有何影響。 在嘗試查找主鍵時,它是否會導致數據庫表上的模式鎖定? 它會導致任何應用程序緩慢嗎?

它與部分類方法解決方案 2 的性能相比如何? 什么選擇在性能方面更好?

注意:架構師要求在工作場所使用存儲庫模式,因此實施它。 知道圍繞這個問題有爭論,但不是我的呼吁。

腳手架模型示例:

namespace Datatest
{
    public partial class Property
    {
        public int Property { get; set; }
        public int DocumentId { get; set; }
        public string Address { get; set; }
    }
}

所有表的示例通用基礎存儲庫:

    public T Get(int id)
    {
        return Table.Find(id);
    }
    public async Task<T> GetAsync(int id)
    {
        return await Table.FindAsync(id);
    }
    public T Single(Expression<Func<T, bool>> predicate)
    {
        return All.Single(predicate);
    }
    public async Task<T> SingleAsync(Expression<Func<T, bool>> predicate)
    {
        return await All.SingleAsync(predicate);
    }
    public T FirstOrDefault(int id)
    {
        return All.FirstOrDefault(CreateEqualityExpressionForId(id));
    }

解決方案 1:FindPrimaryKey()

使用實體框架的 C# 中的通用存儲庫

使用 EF FindPrimaryKey()

var idName = _context.Model.FindEntityType(typeof(TEntity))
        .FindPrimaryKey().Properties.Single().Name;

解決方案2:部分類映射

Net Core:為所有表創建通用存儲庫接口 ID 映射自動代碼生成

public partial class Property: IEntity
{
    [NotMapped]
    public int Id { get => PropertyId; set => PropertyId = value; }
}

關於第一種方法(使用 EF Core 元數據服務):

首先,EF Core 是 ORM(對象關系映射器),這里最重要的是Mapper

其次,它使用所謂的基於代碼的模型,這意味着所有映射都是由代碼提供的,而不是由實際數據庫提供的(即使模型是通過對現有數據庫進行逆向工程創建的)。

簡而言之,EF Core 在運行時創建一個內存數據結構,其中包含有關類和屬性的信息(元數據)以及它們到數據庫表、列和關系的映射。 所有這些信息都基於純代碼模型——實體類、約定、數據注釋和流暢的配置。

所有 EF Core 運行時行為都基於該元數據模型。 EF Core 在構建查詢、將查詢結果映射到對象、鏈接導航屬性、生成創建/更新/刪除命令及其執行順序、在獲取真正的自動生成的主要鍵值后更新臨時 FK 屬性值等時在內部使用它。

因此,元數據模型和發現服務(方法)使用優化的數據結構並且(必須)非常高效。 同樣,涉及數據庫操作。

所以第一種方法非常有效。 與實際的查詢構建、執行和具體化相比,通過元數據服務獲取 PK屬性名稱的性能影響可以忽略不計。

此外,第一種方法的性能類似於您在另一種方法中使用的 EF Core Find方法。 請注意,在調用Find方法時,您只傳遞 PK 值而不是屬性。 所以方法實現應該知道如何構建Where表達式,對嗎? 它在內部所做的與建議的代碼段非常相似。


關於第二種方法:

它根本沒有可比性,因為它不起作用。 可以使用基類/接口,但HasColumnName是映射了實際的屬性名稱 - 就像所有類都具有Id屬性一樣,並且使用[Column]數據注釋或HasColumnName fluent API 將其映射到數據庫表中的不同列名稱

在您的示例中, Id屬性為[NotMapped] (忽略)。 這意味着 EF Core 無法映射到表列。 您通過代碼(屬性 getter/setter)映射到另一個屬性的事實並不重要。 EF Core不是(反)編譯器,它看不到您的代碼,因此無法將使用此類屬性的 LINQ 查詢轉換為 SQL。

在 EF Core 2.x 中,這會導致 客戶端評估(效率非常低,讀取整個表並在內存中應用過濾器),或者如果客戶端評估配置為這樣做,則會導致異常。 而在 EF Core 3.0+ 中,它將始終是一個例外

因此,如果您不刪除諸如PropertyId類的PropertyId映射屬性Id (這對於“數據庫優先”模型來說很困難),則應避免使用第二種“方法”。 即使您可以映射實際的Id屬性,您所節省的時間也只是幾毫秒。 再說一次,在使用Find您不必擔心性能,何必為使用相同(或相似)方法的方法而煩惱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM