簡體   English   中英

使Linq to Sql使用ISNULL而不是COALESCE生成T-SQL

[英]Make Linq to Sql generate T-SQL with ISNULL instead of COALESCE

我有一個linq to sql查詢返回一些非零余額的訂單(實際上,查詢有點復雜,但為了簡單起見,我省略了一些細節)。 此查詢還應該返回沒有CardItems的訂單(兩個子查詢在T-SQL中都返回NULL,並且比較兩個NULLS給出FALSE,因此我將子查詢的NULL結果值轉換為0以進行比較)。

var q = (from o in db.Orders
         where db.Cards(p =>
             p.OrderId == o.Id 
             && p.Sum + (db.CardItems.Where(i => i.IncomeId == p.Id)
                        .Sum(i => (double?)i.Amount) ?? 0) 
                    != (db.CardItems.Where(i => i.DeductId == p.Id)
                        .Sum(i => (double?)i.Amount) ?? 0)
            ).Any()
         select o);

問題是 ,轉換表達式Sum(i =>(double?)i.Amount)?? 0 生成COALESCE運算符,由於其中包含子查詢,因此將COALESCE替換為ISNULL的速度比完全相同的T-SQL查詢慢十倍。 在這種情況下是否有可能生成ISNULL?

根據我的經驗,哄騙linq生成你想要的SQL是最好的麻煩。 如果你有一個比linq更好的查詢實現(正常工作並且運行良好),請繼續使用它,即使只針對這一個查詢。

最快的方法可能是使用DataContext.ExecuteQuery<TResult> 它甚至會為你提供水合和處理返回的對象,就像linq生成查詢本身一樣。

http://msdn.microsoft.com/en-us/library/bb361109.aspx

許多人寧願把這個SQL放在存儲過程中,特別是在生產代碼中。 然后,您只需將存儲過程映射到linq對象中,它的工作方式相同。 通常情況下,ScottGu有一篇關於如何做到這一點的相當詳細的帖子:

http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx

由於您假設沒有Amount的行被歸為零,那么您可以只過濾掉沒有金額的行,並且不用擔心IsNull或coalesce。

&& p.Sum + (db.CardItems.Where(i => i.IncomeId == p.Id)
                    .Where(i=> i.Amount > 0)
                    .Sum(i => (double?)i.Amount) ?? 0) 
                != (db.CardItems.Where(i => i.DeductId == p.Id)
                    .Where(i=> i.Amount > 0)
                    .Sum(i => (double?)i.Amount) ?? 0)

由於我不知道你的對象,你甚至可以刪除強制轉換(雙?)和默認(??)運算符

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM