2011-04-04 297 views
0

我有這樣的SQL查詢:LINQ和SQL查詢比較

SELECT Sum(ABS([Minimum Installment])) AS SumOfMonthlyPayments FROM tblAccount 
INNER JOIN tblAccountOwner ON tblAccount.[Creditor Registry ID] = tblAccountOwner. 
[Creditor Registry ID] AND tblAccount.[Account No] = tblAccountOwner.[Account No] 
WHERE (tblAccountOwner.[Account Owner Registry ID] = 731752693037116688) 
AND (tblAccount.[Account Type] NOT IN 
('CA00', 'CA01', 'CA03', 'CA04', 'CA02', 'PA00', 'PA01', 'PA02', 'PA03', 'PA04')) 
AND (DATEDIFF(mm, tblAccount.[State Change Date], GETDATE()) <= 
4 OR tblAccount.[State Change Date] IS NULL) 
AND ((tblAccount.[Account Type] IN ('CL10','CL11','PL10','PL11')) OR 
CONTAINS(tblAccount.[Account Type], 'Mortgage')) AND (tblAccount.[Account Status ID] <> 999) 

我創建LINQ查詢:

var ownerRegistryId = 731752693037116688; 
var excludeTypes = new[] 
{ 
    "CA00", "CA01", "CA03", "CA04", "CA02", 
    "PA00", "PA01", "PA02", "PA03", "PA04" 
}; 

var maxStateChangeMonth = 4; 
var excludeStatusId = 999; 
var includeMortgage = new[] { "CL10", "CL11", "PL10", "PL11" }; 

var sum = (
    from account in context.Accounts 
    from owner in account.AccountOwners 
    where owner.AccountOwnerRegistryId == ownerRegistryId 
    where !excludeTypes.Contains(account.AccountType) 
    where account.StateChangeDate == null || 
     (account.StateChangeDate.Month - DateTime.Now.Month) 
      <= maxStateChangeMonth 
    where includeMortgage.Contains(account.AccountType) || 
     account.AccountType.Contains("Mortgage") 
    where account.AccountStatusId != excludeStatusId 
    select account.MinimumInstallment).ToList() 
    .Sum(minimumInstallment => 
     Math.Abs((decimal)(minimumInstallment))); 

return sum; 

難道他們平等/一樣的嗎?我沒有db中的記錄,所以我不能確認它們是否相等。在SQL中有括號(),但在Linq中,我沒有使用它們,所以它可以嗎?

請建議。

回答

1

對於我們來說這是不可能的,因爲你沒有向我們展示DBML。模型和數據庫之間映射的實際定義對於能夠看到它是如何執行很重要。

但你的DBML添加到您的問題之前:我們不是在這裏做你的工作,所以這裏有兩個小技巧,瞭解它們是否相等或不:在你的數據庫

  1. 插入數據和運行查詢。
  2. 使用SQL分析器並查看您的LINQ提供者在封面下執行的查詢。

如果您有更具體的問題,我們將非常樂意提供幫助。

+0

嗨史蒂文:我只是想知道,如果我已經正確地翻譯了SQL? – DotnetSparrow 2011-04-04 08:07:51

+0

@DotnetSparrow:我知道你想要的,但正如我在答案中所說:我們不能告訴你,因爲缺少信息,即使沒有:代碼片段太大。你必須自己弄明白。希望我的提示和其他提示能夠幫助你找到你的問題的答案。 – Steven 2011-04-04 08:37:41

1

如有必要,括號將由LINQ提供程序生成。
檢查LINQ查詢是否與初始SQL查詢相等的最簡單方法是將其記錄爲@Atanas Korchev建議的值。
如果您正在使用實體框架,但是,沒有登錄屬性,但你可以嘗試將您的查詢轉換爲的ObjectQuery,並調用然後ToTraceString方法:
string sqlQuery = (sum as ObjectQuery).ToTraceString();
UPD。 ToTraceString方法需要一個用於跟蹤的ObjectQuery實例,並且ToList()調用已經執行實現,所以沒有任何可跟蹤的內容。以下是更新的代碼:

var sum = (
from account in context.Accounts 
from owner in account.AccountOwners 
where owner.AccountOwnerRegistryId == ownerRegistryId 
where !excludeTypes.Contains(account.AccountType) 
where account.StateChangeDate == null || 
    (account.StateChangeDate.Month - DateTime.Now.Month) 
     <= maxStateChangeMonth 
where includeMortgage.Contains(account.AccountType) || 
    account.AccountType.Contains("Mortgage") 
where account.AccountStatusId != excludeStatusId 
select account.MinimumInstallment); 
string sqlQuery = (sum as ObjectQuery).ToTraceString(); 

請注意,此代碼不會執行實際查詢,它僅用於測試目的。 如果您對即時生產日誌實施感興趣,請查看this article

+0

和@Atanas:我在MVC應用程序中工作,所以trace可以在那裏使用,或者context.log可以被訪問? – DotnetSparrow 2011-04-04 08:34:53

+0

嗨@Devart:當我使用TraceString時出現這個錯誤:無法通過引用轉換,裝箱轉換,取消裝箱轉換,包裝轉換或空類型轉換將類型'decimal'轉換爲'System.Data.Objects.ObjectQuery' – DotnetSparrow 2011-04-04 10:08:52

+0

@ DotnetSparrow,看看更新。 – Devart 2011-04-04 10:25:47

0

可以有性能差異:

SQL查詢直接的單個數字(SELECT Sum...)從數據庫服務器返回到執行該查詢的客戶端。

在你的LINQ查詢你有之間的貪婪操作符(.ToList()):

var sum = (... 
    ... 
    select account.MinimumInstallment).ToList() 
    .Sum(minimumInstallment => 
     Math.Abs((decimal)(minimumInstallment))); 

這意味着,在SQL服務器上查詢不包含.Sum操作。查詢返回MinimumInstallments的一個(可能很長?)列表。然後在客戶端的內存中執行.Sum操作。

如此有效地在.ToList()之後從LINQ切換到實體切換到對象。

順便說一句:你可以檢查你的previous question here中的最後一個建議,它會避免.ToList()這個查詢(如果提案應該工作)並因此更接近SQL語句。

+0

@Saluma:我試過了,但我仍然得到了同樣的錯誤,所以我用了tolist並且沒有了。 – DotnetSparrow 2011-04-04 10:29:40

+0

@DotnetSparrow:我看到,在上一個問題中有一個新的Edit。 – Slauma 2011-04-04 11:18:57