2013-09-23 60 views
0

我是新來的實體框架。這是我第一個使用它的項目。如何使用EF5填充擴展方法並返回IQueryable(無循環)

我創建了一個新類,它使用新屬性擴展我的「商人」實體,這些新屬性大多數是總計。我無法弄清楚用數據填充這些新屬性的最佳方式。我使用breeze.js來查詢一個iQueryable端點,所以我需要保持這個功能不變。

我發現了以下解決方案,但速度很慢,因爲我必須遍歷每條記錄。儘管我已經在微風中實現了分頁,但循環仍然會觸及每一條記錄,儘管它只返回一頁。我想這就是實體框架的工作原理。我的問題是我如何填充擴展屬性沒有循環?

這是我的代碼,但它很慢。我可以消除這個循環並用值填充該擴展屬性嗎?

[HttpGet] 
    public IQueryable<Merchant> MerchantList() 
    { 
     IQueryable<Merchant> items = _repo.Context.Merchants; 

     foreach (var item in items) 
     { 

      // Total Stores 
      item.TotalStores = myMethod(item.MerchantUID); 

     } 

     return items; 

    } 
+0

您正在尋找'Include'方法。 –

+0

我真的很感謝答覆。我正在研究這個Include方法,它似乎用於「加載」通常導致連接的相關實體。我並沒有真正瞭解這將如何幫助我將數據加載到擴展屬性並避免循環。如果你有時間可以請詳細說明一下嗎? – user2341148

+0

什麼是「myMethod」在做什麼?根據您傳入的內容,是否可以使用Merchant類中的其他屬性來填充TotalStores? – cbeckner

回答

0

通過它您通過在關閉的機會,有人價值數據的整個表循環的容貌得到某些行。我並不熟悉Breeze,但我希望此解決方案能夠爲您工作之前,我已與OData一起工作。

我建議你停止公開IQueryable<>並在內部管理查詢。這將使您可以將附加信息添加到您要返回給客戶端的記錄中。下面是一些粗糙的代碼,你指出正確的方向:

[HttpGet] 
public PageResult<Merchant> MerchantList(
    ODataQueryOptions<Merchant> queryOptions) 
{ 
    var t = new ODataValidationSettings() { MaxTop = 25 }; 
    var s = new ODataQuerySettings() { PageSize = 25 }; 
    queryOptions.Validate(t); 
    IEnumerable<Merchant> results = 
     (IEnumerable<Merchant>)queryOptions.ApplyTo(_repo.Context.Merchants, s); 

    int skip = queryOptions.Skip == null ? 0 : queryOptions.Skip.Value; 
    int take = queryOptions.Top == null ? 25 : queryOptions.Top.Value; 
    long? count = Request.GetInlineCount(); 

    List<Merchant> pageOfResults = results.Skip(skip).Take(take).ToList(); 

    PageResult<Merchant> page = 
     new PageResult<Merchant>(
      pageOfResults, 
      Request.GetNextPageLink(), 
      Request.GetInlineCount()); 

    foreach (var item in page) 
    { 

     // Total Stores 
     item.TotalStores = myMethod(item.MerchantUID); 

    } 

    return page; 
} 

using小號

using System.Web.Http; 
using System.Web.Http.OData; 
using System.Web.Http.OData.Builder; 
using System.Web.Http.OData.Query; 
+0

謝謝。我會檢查Breeze文檔,看看這是否兼容。如果是這樣,那麼它似乎是一個不錯的解決方案。 – user2341148

0

感謝大家的方向。最接近的建議是關於使用oData的建議。我研究了急切的加載,但似乎適用於加入實體,這些屬性不能合併。我可能會用「include」做更多的研究,以確定它是否可以用來加載單個屬性,但是我找不到任何以這種方式使用的文檔。接近的另一件事是投影,但是EF不允許投影到相同類型。我本可以投影到一個部分類,但是我會放鬆微風需要的元數據。如果不是微風,那將是一個非常好的解決方案。最後,雖然Breeze支持oData,但它有太多限制(比如無法緩存),所以我想留在IQueryable中。

這就是我想出來的。它現在只循環遍歷當前頁面,但它仍然會記錄主查詢,所以Breeze可以在客戶端上進行分頁。這是完全可能的,因爲Breeze允許我發送獲取參數,所以我可以將分頁卸載到服務器。這花了大量的研究,但它仍然不是完美的,但它加載速度非常快,所以現在我必須繼續前進。

[HttpGet] 
    [BreezeQueryable] 
    public QueryResult MerchantList(int take, int skip) 
    { 

     IQueryable<Merchant> main = _repo.Context.Merchants.OrderBy(m => m.MerchantUID); 

     IQueryable<Merchant> items = main.Skip(skip).Take(take); 
     foreach (var item in items) 
     { 

      // Total LifetimeVal 
      item.LifetimeVal= TotalLifetimeVal(item.MerchantUID); 

      // Total Stores 
      item.TotalStores = TotalStores(item.MerchantUID); 

     } 


     // return items; 
     return new QueryResult 
     { 
      InlineCount = main.Count(), 
      Results = items.ToList() 
     }; 

    } 
+0

當人們不清楚循環中的方法是什麼時,這對他人來說並沒有多大意義。它看起來像你可以利用急於加載時,而不是'item.MerchantUID'通過'item',但是,誰知道? –

+0

這對使用Breeze JS的人來說意味着什麼。它使分配擴展屬性成爲可能,而無需循環遍歷整個表格。我還解決了不丟失元數據,這對Breeze來說非常重要。它會更好嗎?也許,但它做了我想要的。另外,沒有人向我展示一個渴望加載任意屬性的例子。我明白你急於加載其他實體(類似於連接)。你能告訴我如何急於加​​載一個任意的方法,例如一個巨大的存儲過程計算的值? – user2341148