LINQ多表左连接,不同计数没有给出正确的结果

时间:2016-08-23 06:49:33

标签: linq

我是SQL查询我们产生正确的结果,但是当我在LINQ中做同样的事情时。输出不正确。请让我知道我犯错的地方。

按照我创建的linq查询。

LINQ查询:

List<UserModel> Model = (from users in db.UserMasters
                     join ct in db.CustTests on users.UserId equals ct.UserID into group1
                     from g1 in group1.DefaultIfEmpty()
                     join ti in db.TestInvitaions on  g1.TestId equals ti.TestID into group2
                     from g2 in group2.DefaultIfEmpty()
                     where (users.CustomerId==UserSession.CustomerId) && (users.RoleId == 4) && (users.Status == 1)
                     group new
                     {
                         g2.TestInvitationID,
                         g2.TestID,
                     }
                     by new
                     {
                         users.FirstName,
                         users.CreatedOn,
                         users.Email,
                         users.UserId
                     } into group4

                     select new UserModel
                     {
                         Name =  group4.Key.FirstName,
                         CreatedOn = group4.Key.CreatedOn,
                         EmailId = group4.Key.Email,
                         UserId = group4.Key.UserId,
                         NoOfTestTaken = group4.Select(x=>x.TestID).Distinct().Count(),
                         NoOfInvitationsSent = group4.Count(x => x.TestInvitationID != 0)
                     }).ToList();

SQL查询:

SELECT IsNull(COUNT(distinct TS.TestId),0) AS NoOfTests,
       IsNull(COUNT(TS.TestInvitationID),0) AS NoOfInvitations,
       UM.Email,
       UM.UserId,
       UM.FirstName,
       UM.CreatedOn 
FROM UserMaster as UM  
left JOIN CustTest AS CT 
ON UM.UserId=CT.UserId  
left JOIN TestInvitaions AS TS 
ON TS.TestId = CT.TestId 

WHERE UM.CustomerId=41  
AND UM.RoleId=4 
and UM.[Status]=1 

GROUP BY UM.UserId, UM.Email, UM.FirstName, UM.CreatedOn

表:

  • &#34; UserMaster&#34; - 列:UserId,Email,FirstName,CreatedOn
  • &#34; CustTest&#34; - columns:TestId,UserId,
  • &#34; TestInvitaions&#34; - columns:TestInvitationId,TestId

2 个答案:

答案 0 :(得分:2)

SQL COUNT(expr)和LINQ Count之间的区别在于前者排除NULL值,当在左外连接的右侧使用时没有匹配的记录会产生差异( LINQ 0时SQL将生成1。最接近的LINQ等价物是Count(expr != null)

因此,您的SQL查询的直接翻译将是这样的(请注意,生成的SQL查询可能并且很可能会有所不同):

(旁注:将SQL查询转换为LINQ时,使用相同的别名可以更容易地查看映射)

var query = 
    from um in db.UserMasters
    join ct in db.CustTests on um.UserId equals ct.UserID
    into ctGroup from ct in ctGroup.DefaultIfEmpty() // left outer join
    join ts in db.TestInvitaions on ct.TestId equals ts.TestID
    into tsGroup from ts in tsGroup.DefaultIfEmpty() // left outer join
    where um.CustomerId == UserSession.CustomerId
       && um.RoleId == 4
       && um.Status == 1
    group ts by new { um.UserId, um.Email, um.FirstName, um.CreatedOn } into g
    select new UserModel
    {
        Name =  g.Key.FirstName,
        CreatedOn = g.Key.CreatedOn,
        EmailId = g.Key.Email,
        UserId = g.Key.UserId,
        NoOfTestTaken = g.Where(ts => ts != null).Select(ts => ts.TestID).Distinct().Count(),
        NoOfInvitationsSent = g.Count(ts => ts != null)
     };

var result = query.ToList();

答案 1 :(得分:0)

我怀疑以下行是问题,因为与你的sql不一样:

  • 的LINQ:

    NoOfInvitationsSent = group4.Count(x => x.TestInvitationID != 0)
    
  • SQL:

    IsNull(COUNT(TS.TestInvitationID),0) AS NoOfInvitations
    
  • 由于计算来自左连接的项目,Linq应改为:

    NoOfInvitationsSent = group4.Where(i => i != null).Count()
    

将所有内容放在一起,并提供更好的格式化:

var model = (from users in db.UserMasters
             join ct in db.CustTests on users.UserId equals ct.UserID into group1
             from ct in group1.DefaultIfEmpty()
             join ti in db.TestInvitaions on  ct.TestId equals ti.TestID into group2
             from ct in group2.DefaultIfEmpty()

             where users.CustomerId == UserSession.CustomerId && 
                   users.RoleId == 4 && 
                   users.Status == 1

             group new { ct.TestInvitationID, ct.TestID }
             by new
             {
                 users.FirstName,
                 users.CreatedOn,
                 users.Email,
                 users.UserId
             } into grouping

             select new UserModel
             {
                 Name =  grouping.Key.FirstName,
                 CreatedOn = grouping.Key.CreatedOn,
                 EmailId = grouping.Key.Email,
                 UserId = grouping.Key.UserId,
                 NoOfTestTaken = grouping.Where(i => i != null).Select(x => x.TestID).Distinct().Count(),
                 NoOfInvitationsSent = grouping.Where(i => i != null).Count()
             }).ToList();