2011-06-22 266 views
2

我有這個查詢在Books,TradingDesks和ProductInfos上運行聯接。這些數據在每個集合中都很龐大。LINQ查詢幫助

var queryJoin = from b in books.Values 
            join d in tradingDesks.Values 
             on b.TradingDeskId equals d.Id 
            join p in ProductInfos.Values 
             **on b.Id equals p.RiskBookId** 
            select new { p, Book = b.Name, TradingDeskName = d.Name }; 

在突出顯示的行(on b.Id equals p.RiskBookId),我也想添加像,(on b.Id equals p.RiskBookId || p.RiskBookId == 0)另一個條件。我如何在這個linq語法中做到這一點。

我想查詢這樣

var queryJoin = from b in books.Values 
       from d in tradingDesks.Values.Where(x => x.Id == b.TradingDeskId) 
       from p in cachedProductInfos.Values.Where(y => y.RiskBookId == b.Id) 
       select new { p, Book = b.Name, TradingDeskName = d.Name }; 

但是,在這種情況下,查詢將永遠運行下去,我耗盡內存。 。所以我猜它構圖以這種方式做一些瘋狂:(

任何幫助表示讚賞

感謝 瑪尼

+0

這似乎是完全的LINQ到對象,我沒有看到那裏的LINQ到SQL適合 – Aducci

回答

2

在原來的查詢,以Enumerable.Join這些電話使用的是哈希表在幕後做事情快。如果你切換到.Where,你沒有得到這些哈希好處。您可以明確使用散列來獲得相同的效果。

ILookup<int, string> deskNameLookup = tradingDesks.Values 
    .ToLookup(
    d => d.Id, 
    d => d.Name 
); 

ILookup<int, ProductInfo> infoLookup = ProductInfos.Values 
    .ToLookup(p.RiskBookId); 

foreach(b in books.Values) 
{ 
    foreach(dName in deskNameLookup[b.TradingDeskId]) 
    { 
    foreach(p in infoLookup[b.Id].Concat(infoLookup[0])) 
    { 
     var x = new {p, Book = b.Name, TradingDeskName = dName}; 
    } 
    } 
} 
+0

感謝大衛,這看起來更有希望,但我堅持使用這個選項,因爲我有這個查詢表達式作爲IQuerayble,並做進一步更多關於這個的操作任何有關如何將它加載到IQueryable中的想法? –

+0

將此標記爲答案,但這不能解決問題,這就解釋了爲什麼我的查詢需要比平常更長的時間。 –

-1

其實:

join d in tradingDesks.Values 
    on (b.Id equals p.RiskBookId || p.RiskBookId equals 0) 

on (b.Id == p.RiskBookId || p.RiskBookId == 0) 

應該工作完美。

連接需要一個真正的條件:

on <expression> 

(b.Id equals p.RiskBookId || p.RiskBookId == 0) 

將返回true或false,所以加入應評估,僅僅如此。

+0

這不會編譯!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VAR queryJoin =從步驟b中books.Values 在tradingDesks.Values加入d 上b.TradingDeskId等於d.Id 在cachedProductInfos.Values 加入p(b.Id等於p.RiskBookId || p.RiskBookId等於0) 選擇新{p,Book = b.Name,TradingDeskName = d.Name}; –

+0

不,這不會編譯。 –

+0

很好 - Linq和SQL很相似。 :) –

0

equals只能用於做單個比較。

其他人可能會給你一個優化的方法來查詢你的情況,但增加到equals條件不是在這裏的解決方案。最好的做法是以一種不同的方式來處理它 - 而不是通過單個查詢的主體內部的所有數據 - 通過某種定製的加載和緩存機制,因爲數據的大小顯然是有問題的。

0

試試這個,有點逐字但像你描述它應該工作:

var queryJoin = 
    from b in books.Values 
    join d in tradingDesks.Values on b.TradingDeskId equals d.Id 
    let p = 
     from pi in ProductInfos.Values 
     where (b.Id == pi.RiskBookId) || (pi.RiskBookId == 0) 
     select pi 
    where p.Any() 
    select new 
    { 
     p, 
     Book = b.Name, 
     TradingDeskName = d.Name 
    }; 
+0

沒有。這也不工作。超時! :( –

+0

問題可能是'(pi.RiskBookId == 0)',這取決於你的數據,如果你有大量的記錄與該條件 –

+0

你是對的。從另一個角度思考它,我需要的就像一個外部連接在ProductInfo集合上仍然工作在同一個,沒有解決方案呢...... –

1

你可以嘗試制定它作爲一個工會,而不是單個連接:

var baseQuery = 
    from book in books.Values 
    join desk in tradingDesks.Values on book.TradingDeskId equals desk.Id 
    select new {book, desk}; 

var conditionOne = 
    from baseQ in baseQuery 
    join productInfo in ProductInfos.Values on baseQ.book.Id equals productInfo.RiskBookId 
    select new 
    { 
     productInfo, 
     Book = baseQ.book.Name, 
     TradingDeskName = baseQ.desk.Name 
    }; 

var conditionTwo = 
    from baseQ in baseQuery 
    join productInfo in ProductInfos.Values on book.Id equals 0 
    select new 
    { 
     productInfo, 
     Book = baseQ.book.Name, 
     TradingDeskName = baseQ.desk.Name 
    }; 

var result = conditionOne.Union(conditionTwo);