2011-04-04 169 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