我已經通過 SQL Server Profiler 檢查了 EF Core 6,這從性能的角度來看是令人震驚的。
這里沒有任何介紹,這是非常好的:
var user = App.Ctx.LoginUsers;
這段代碼沒有進行任何分析,這也很好:
user = App.Ctx.LoginUsers;
在這里,分析的代碼也很好:
var users = App.Ctx.LoginUsers.ToList();
但是使用此代碼,在分析時非常糟糕,因為它已經在上面的背景關系記憶體中:
users = App.Ctx.LoginUsers.ToList();
如果每個查詢都從 SQL Server 取整,即使它在背景關系記憶體中,那么性能會是災難嗎?
但是我們期望僅針對已更改的差異資料往返 SQL 服務器
插入以添加到 dbcontext 記憶體中
僅修改為在 dbcontext 記憶體中更新
并且只有 Deleted 才能從 dbcontext 記憶體中洗掉
并提供來自 dbcontext 記憶體的任何詢問資料的資料。
通過這種方式,我們認為性能會大幅提升。
uj5u.com熱心網友回復:
如果每個查詢都來自 sql server
是的,這就是查詢的作用。他們從資料庫中獲取資料。如果要訪問先前查詢中加載的資料,請使用DbSet< TEntity >.Local,或將它們存盤在您自己的集合中。
DbContext Change Tracker 存盤從您的資料庫中檢索到的物體,但它并非設計為通讀快取。如果您運行另一個查詢,另一個查詢將發送到資料庫。
uj5u.com熱心網友回復:
你所說的“災難”是什么意思?
默認情況下,EF 將跟蹤它已經獲取的參考。不要將此與快取混淆,因為它是出于性能原因。將整組物體加載為跟蹤參考并不是一個好主意。不是因為盡管這些實體已經被跟蹤,但它仍然意味著額外的資料庫往返,而是因為 EFDbContext跟蹤的實體越多,使用的記憶體越多,獲取額外資料所需的時間就越長,因為這些操作將自動尋找將任何已經跟蹤的實體與回傳的資料的任何關系相關聯。
如果您獲取大量資料并且不需要 DbContext 跟蹤該資料(即您不打算更新它,因此您不需要更改跟蹤),則使用 AsNoTracking()。
var users = App.Ctx.LoginUsers.AsNoTracking().ToList();
這仍然會從資料庫中獲取所有用戶,但背景關系不會跟蹤這些實體。
如果你知道你已經加載了所需的資料,或者想要在進入資料庫之前檢查和使用任何預加載和跟蹤的實體,那么使用LocalDbSet 中的集合告訴 EF 只轉到跟蹤實體:
// Look for a tracked instance:
var user = App.Ctx.LoginUsers.Local.SingleOrDefault(x => x.UserId == userId);
if (user == null)
user = App.Ctx.LoginUsers.Single(x => x.UserId == userId);
當您知道某些資料可能已經被跟蹤并且您正在處理分離的物體時,這是一種常見的策略。(即用戶加載AsNoTracking或反序列化)該Local呼叫檢查該物體的跟蹤存盤,因此沒有到 DB 的往返行程,然后如果我們找不到它,我們可以從 DB 加載和跟蹤它。
要注意的另一個細節是,雖然針對 DbContext 的查詢將回傳已跟蹤的實體仍會觸發 SQL 查詢,但被跟蹤的實體不會被該查詢回傳的資料更新。例如,如果您將用戶加載到 DbContext 中,那么其他一些不使用該 DbContext 實體的行程會修改資料庫中的一個或多個用戶,從 DbContext 中獲取這些用戶將回傳跟蹤的資料加載。將針對資料庫運行 SQL 查詢,但是任何修改的資料狀態都不會自動更新任何已跟蹤的物體。
uj5u.com熱心網友回復:
但是我們期望往返SQL服務器
僅適用于已更改的差異資料
插入以添加到 dbcontext 記憶體中
僅修改為在 dbcontext 記憶體中更新
并且只有Deleted才能從 dbcontext 記憶體中洗掉
并僅提供來自 dbcontext 記憶體的資料。
通過這種方式,我們認為性能會大幅提升。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/402927.html
標籤:
上一篇:ForEach回圈的ForEachFile列舉器運算式中的“name”屬性是什么?
下一篇:憑據選擇彈出視窗未出現
