这个LINQ语法有什么问题?

时间:2010-05-15 06:36:53

标签: c# sql linq linq-to-sql

我正在尝试将SQL查询转换为LINQ。不知怎的,我的计数(distinct(x))逻辑似乎没有正常工作。原始SQL非常有效(或者我认为),但生成的SQL甚至没有返回正确的结果。

我正在尝试修复此LINQ以执行原始SQL正在执行的操作,并且以原始查询正在执行的有效方式执行。因为我被困在这里,所以这里的帮助真的很难得:(

SQL正在运行,我需要制作一个类似的LINQ:

SELECT  [t1].[PersonID] AS [personid]
FROM [dbo].[Code] AS [t0]
INNER JOIN [dbo].[phonenumbers] AS [t1] ON [t1].[PhoneCode] = [t0].[Code]
INNER JOIN [dbo].[person] ON [t1].[PersonID]= [dbo].[Person].PersonID
WHERE ([t0].[codetype] = 'phone') AND (
([t0].[CodeDescription] = 'Home') AND ([t1].[PhoneNum] = '111') 
OR
([t0].[CodeDescription] = 'Work') AND ([t1].[PhoneNum] = '222') )
GROUP BY [t1].[PersonID] HAVING COUNT(DISTINCT([t1].[PhoneNum]))=2

我所做的LINQ大致如下:

 var ids = context.Code.Where(predicate);
            var rs = from r in ids
                     group r by new { r.phonenumbers.person.PersonID} into g
                     let matchcount=g.Select(p => p.phonenumbers.PhoneNum).Distinct().Count()
                     where matchcount ==2
                     select new
                  {
                      personid = g.Key
                  };

不幸的是,上面的LINQ没有生成正确的结果,实际上是在内部生成到下面显示的SQL。顺便说一句,由于COUNTS,这个生成的查询也会读取所有行(约19592040)2次左右:(这也是一个很大的性能问题。请帮助/指出正确的方向。

Declare @p0 VarChar(10)='phone'
Declare @p1 VarChar(10)='Home'
Declare @p2 VarChar(10)='111'
Declare @p3 VarChar(10)='Work'
Declare @p4 VarChar(10)='222'
Declare @p5 VarChar(10)='2'

SELECT [t9].[PersonID], (
    SELECT COUNT(*)
    FROM (
        SELECT DISTINCT [t13].[PhoneNum]
        FROM [dbo].[Code] AS [t10]
        INNER JOIN [dbo].[phonenumbers] AS [t11] ON [t11].[PhoneType] = [t10].[Code]
        INNER JOIN [dbo].[Person] AS [t12] ON [t12].[PersonID] = [t11].[PersonID]
        INNER JOIN [dbo].[phonenumbers] AS [t13] ON [t13].[PhoneType] = [t10].[Code]
        WHERE ([t9].[PersonID] = [t12].[PersonID]) AND ([t10].[codetype] = @p0) AND ((([t10].[codetype] = @p1) AND ([t11].[PhoneNum] = @p2)) OR (([t10].[codetype] = @p3) AND ([t11].[PhoneNum] = @p4)))
        ) AS [t14]
    ) AS [cnt]
FROM (
    SELECT [t3].[PersonID], (
        SELECT COUNT(*)
        FROM (
            SELECT DISTINCT [t7].[PhoneNum]
            FROM [dbo].[Code] AS [t4]
            INNER JOIN [dbo].[phonenumbers] AS [t5] ON [t5].[PhoneType] = [t4].[Code]
            INNER JOIN [dbo].[Person] AS [t6] ON [t6].[PersonID] = [t5].[PersonID]
            INNER JOIN [dbo].[phonenumbers] AS [t7] ON [t7].[PhoneType] = [t4].[Code]
            WHERE ([t3].[PersonID] = [t6].[PersonID]) AND ([t4].[codetype] = @p0) AND ((([t4].[codetype] = @p1) AND ([t5].[PhoneNum] = @p2)) OR (([t4].[codetype] = @p3) AND ([t5].[PhoneNum] = @p4)))
            ) AS [t8]
        ) AS [value]
    FROM (
        SELECT [t2].[PersonID]
        FROM [dbo].[Code] AS [t0]
        INNER JOIN [dbo].[phonenumbers] AS [t1] ON [t1].[PhoneType] = [t0].[Code]
        INNER JOIN [dbo].[Person] AS [t2] ON [t2].[PersonID] = [t1].[PersonID]
        WHERE ([t0].[codetype] = @p0) AND ((([t0].[codetype] = @p1) AND ([t1].[PhoneNum] = @p2)) OR (([t0].[codetype] = @p3) AND ([t1].[PhoneNum] = @p4)))
        GROUP BY [t2].[PersonID]
        ) AS [t3]
    ) AS [t9]
WHERE [t9].[value] = @p5

谢谢!

2 个答案:

答案 0 :(得分:0)

我认为问题可能是new { r.phonenumbers.person.PersonID}

为什么要在这里新建一个新对象而不是直接按r.phonenumbers.person进行分组? new {}每次都会成为一个不同的对象,永远不会分组。

按人分组后,我会Select group => new {person = group.person, phoneNumbers = group.person.phonenumbers},然后检查他们拥有多少个电话号码,然后进行最终投影。

答案 1 :(得分:0)

Drats!看起来这个错误就在我身边(GIGO原则!)

在我的ORM中,我从右到左创建了关联,而不是相反。我认为这就是问题所在。

现在只剩下问题了LINQ正在以两次方式生成一个INNER JOIN,这样可以保持最终结果的正确检索。如果我在生成的sql中发表评论,我会得到正确的结果。这是现在唯一的问题,我想我会为此提出一个新问题。谢谢你的时间!。