0

我們的一個承包商使用代碼優先方法實施了存儲庫模式。我們使用Service Locator作爲DI模式。當我們從數據庫中檢索數據時,我們做了什麼,我們將接口傳遞給GetQueryable函數並獲取數據。但是,我發現應用程序存在嚴重的性能問題。我實現了MiniProfiler和MiniProfiler.EF來查看瓶頸在哪裏。實體框架5中的許多重複查詢代碼優先(n + 1)

我們有一個包含很多字段(大約25個)的案例表,其中一些字段與其他表格以一對一和一對多關聯(只有一個字段與其他表格有很多關係)。當我嘗試查看案例詳細信息時,它會運行大約400個SQL查詢,並且SQL佔用大約40%的加載時間,直至涉及小型資源分配器。這裏我們的GetQueryable和查找方法

 public IQueryable<T> GetQueryable<T>(params string[] includes) 
    { 
     Type type = _impls.Value[typeof (T).Name].GetType(); 
     DbSet dbSet = Db.Set(type); 
     foreach (var include in includes) 
     { 
      dbSet.Include(include); 
     } 
     return ((IQueryable<T>) dbSet); 
    } 

我添加了這個方法來附加其他相關的表,但它沒有任何區別。這裏是查找方法

public T Find<T>(long? id) 
    { 
     Type type = _impls.Value[typeof(T).Name].GetType(); 
     return (T) Db.Set(type).Find(id); 
    } 

我幾乎試圖應用所有的性能改進,但SQL查詢的數量沒有下降。我試圖禁用延遲加載,但在應用程序的其他部分導致了許多問題。

只是一些額外的信息,在案例表中,有70000行,在對話框表中,有500000行。 Case和Dialog是一對多關聯的。每個案例有20-40個對話條目。

我的問題是;

  • 爲什麼包括我在使用時沒有什麼區別?
  • 是否有任何其他方式來裁剪運行的查詢數量?
  • 您認爲實施是問題嗎?

感謝

+0

你的底層查詢是什麼?只有在不改變原始查詢的情況下,「Include」纔有效。您的查詢必須返回您開始查詢的對象類型。你可以發佈Db課程嗎? – Justin

+0

基本上查詢是,var case = Locator.Facade.GetQueryableFor ().Sincle(k => k.Id == caseId); – AnarchistGeek

+0

我想知道'Db.Set'是否對查詢造成不良影響。你能告訴我們該代碼做什麼嗎? – Justin

回答

1

第1步:啓動您的承包商。認真。就像現在一樣。這是一些可怕的的代碼。他們不僅錯過了像使用通用版本Set一樣簡單和基本的東西,而且他們僅僅成功地使實體框架更加複雜,因爲所有的存儲庫都是代理實體框架方法,它們擁有自己獨特的和混雜的API。

也就是說,這裏確實沒有足夠的診斷你的問題。使用Include可能會給你更大的查詢,但它實際上應該用於減少發出的查詢的總數。這是可能的,你只是沒有使用包括你應該在哪裏。

現在,您「試圖禁用延遲加載,但在應用程序的其他部分導致了很多問題」這一事實,意味着您過度依賴延遲加載。基本上,你正在加載你甚至不知道的東西,這是優化的對立面。具有諷刺意味的是,通過繼續前進並禁用延遲加載,然後追蹤代碼因此而失敗的位置,實際上可以爲您提供最好的服務。如果您想實際延遲加載該內容,則可以使用.Load(請參閱:Explicit Loading)。但是,如果您想急於加載以減少查詢,那麼您知道需要添加哪些內容。

+0

謝謝你..他已經走了:) – AnarchistGeek

2

Include回報IQueryable並不會修改源查詢。此外,您可以使用Set通用版本簡化了代碼位:

public IQueryable<T> GetQueryable<T>(params string[] includes) 
{ 
    IQueryable<T> query = Db.Set<T>(); 
    foreach (var include in includes) 
    { 
     query = query.Include(include); 
    } 
    return query; 
} 
+0

我會試試,但您認爲這會讓我獲得一些表現嗎? – AnarchistGeek

+0

@AnarchistGeek:它會使'包括'工作,因爲它應該。這可能會減少400個查詢的數量,因爲不再需要延遲加載(假設你應用* right * includes)。 – Slauma