2011-10-01 24 views
1

我有一個頁面將來自兩個不同表格的聚集數據組合在一起。我希望並行執行這些查詢,以減少延遲,而不必引入可執行這兩個操作的存儲過程。在沒有存儲過程的情況下在EF4中執行同時無關的查詢?

例如,我現在有這樣的:

ViewBag.TotalUsers = DB.Users.Count(); 
ViewBag.TotalPosts = DB.Posts.Count(); 
// Page displays both values but has two trips to the DB server 

我想一個類似於:

var info = DB.Select(db => new { 
    TotalUsers = db.Users.Count(), 
    TotalPosts = db.Posts.Count()); 
// Page displays both values using one trip to DB server. 

會產生這樣的

SELECT (SELECT COUNT(*) FROM Users) AS TotalUsers, 
     (SELECT COUNT(*) FROM Posts) AS TotalPosts 

因此查詢,我正在尋找一個查詢來擊中數據庫服務器。我不問如何使用並行任務或線程

很顯然,我可以創建行程單回來的兩個值的存儲過程兩個單獨的查詢,但我想避免,如果可能的,因爲它更容易純粹在代碼中添加額外的統計信息,而不是不斷刷新數據庫導入。

我錯過了什麼嗎? EF中有一個很好的模式可以說你想要幾個不同的值可以並行取出嗎?

+0

我猜測帖子與用戶無關? –

+0

對。我只是編制了這兩個表名。我的實際是其他東西是不相關的 –

+1

我意識到這並沒有真正幫助你,但我認爲值得注意的是,NHibernate有一個名爲'期貨'的概念,它有相同的事情(即多個查詢在一個請求中)。 – StanK

回答

0

EF4中似乎還沒有好的方法可以做到這一點。你可以:

  1. 使用adrift描述的技術會產生一個稍微尷尬的查詢。
  2. 使用ExecuteStoreQuery其中T是您創建的某個虛擬類,其中屬性獲取器/設置器與查詢中列的名稱匹配。這種方法的缺點是你不能直接使用你的實體模型,而必須求助於SQL。另外,你必須創建這些虛擬實體。
  3. 使用a MultiQuery class that combines several queries into one。這與Stankin在評論中暗示的NHibernate的未來相似。這是一個小黑客,它似乎並不支持標量值查詢(還)。
0

你應該可以用Parallel LINQ(PLINQ)完成你想要的。你可以找到一個介紹here

+0

我很熟悉PLINQ,但這種方法並不像我想的那樣優化。我寧願讓EF將我的請求重寫爲單個查詢。我已更新我的問題以反映這一點。 –

1

這將使用單個select聲明返回計數,但有一個重要警告。您會注意到EF生成的sql使用cross join s,所以必須有一個表(不一定是您計算的那個表),它保證有行,否則查詢將不返回結果。這不是一個理想的解決方案,但我不知道在您的示例中可能生成sql,因爲它在外部查詢中沒有from子句。

下面的代碼計算在Adventure Works的數據庫AddressesPeople表中的記錄,並且依靠StateProvinces至少有1紀錄:

var r = from x in StateProvinces.Top("1") 
     let ac = Addresses.Count() 
     let pc = People.Count() 
     select new { AddressCount = ac, PeopleCount = pc }; 

,這是產生的SQL:

SELECT 
     1 AS [C1], 
     [GroupBy1].[A1] AS [C2], 
     [GroupBy2].[A1] AS [C3] 
FROM  
    (
     SELECT TOP (1) [c].[StateProvinceID] AS [StateProvinceID] 
     FROM [Person].[StateProvince] AS [c] 
    ) AS [Limit1] 
CROSS JOIN 
    (
     SELECT COUNT(1) AS [A1] 
     FROM [Person].[Address] AS [Extent2] 
    ) AS [GroupBy1] 
CROSS JOIN 
    (
     SELECT COUNT(1) AS [A1] 
     FROM [Person].[Person] AS [Extent3] 
    ) AS [GroupBy2] 

,並從查詢的結果時,它運行在SSMS:

C1   C2   C3 
----------- ----------- ----------- 
1   19614  19972 
+0

感謝您的回答。我已經能夠得到類似的東西(在我的例子中,我們使用了一個表格,其中有一列,當前有數據庫模式版本的行)。它也做了交叉連接。我開始認爲在創建存儲過程之外沒有很好的解決方案。這種方法的問題是我幾乎必須爲我的幾個視圖/頁面創建一個sproc來減少延遲。我也嘗試了DB.ExecuteStoredQuery,但無法在不創建自定義實體的情況下使其工作。 –

+0

@Jeff Moser,如果替代方案是你必須創建多個存儲過程,那麼我會考慮使用這種方法,特別是因爲你有一張表,你可以使用它將有一個記錄。由於您正在交叉連接每個只有一行的子查詢,因此我認爲交叉連接的性能不會成爲問題。 –

相關問題