两个看似相同的LINQ查询。一个有效,另一个无效

时间:2014-10-03 01:24:54

标签: c# asp.net-mvc linq

以下查询有效:

var result = (from p in db.Permissions
              join z in db.PermissionOverridesByUsers on p.id equals z.PermissionID into x
              from y in x.DefaultIfEmpty()
              where userRoleIds.Contains((Guid)(p.ParentRoleID))
              select new RolePermissionViewModel
                         {
                             id = p.id,
                             Name = p.Name,
                             IsSet = ((y.id != null && y.id > 0) ? false : true)
                         }).ToList(); // If an exception exists, IsSet = false, otherwise = true.                        

这个在 IsSet

上产生空引用错误
var query1 = (from p in db.Permissions
              where userRoleIds.Contains((Guid)(p.ParentRoleID))
              select p).ToList();

var query2 = (from ov in db.PermissionOverridesByUsers
              where ov.AffectedUserID == id
              select ov).ToList();

var result = (from q1 in query1
              join z in query2 on q1.id equals z.PermissionID into x
              from y in x.DefaultIfEmpty()
              select new RolePermissionViewModel
                         {
                             id = q1.id,
                             Name = q1.Name,
                             IsSet = ((y.id != null && y.id > 0) ? false : true)
                         }).ToList();

我做错了什么?如何使第二个结果工作?

1 个答案:

答案 0 :(得分:1)

查询提供程序会解释您的第一个查询,以生成相应的查询以返回请求的结果。对于查询提供程序,构造join ... into x from y in x.DefaultIfEmpty()是生成左外连接的标志。随着实体的具体化,提供者识别NULL值以及给定类型的相应默认值。这些默认值是在评估涉及它们的表达式时使用的。

当您将所有结果拉入列表时,您的第二个查询将被拉入LINQ to Objects。现在查询这些列表受到常规C#规则的约束。现在x.DefaultIfEmpty()部分现在将生成一个项目的集合,该项目是集合类型的默认值。在引用类型的情况下,这意味着null。您需要提供替代(非空)值才能使用。默认实例通常就足够了。

var result =
    (from q1 in query1
    join z in query2 on q1.id equals z.PermissionID into x
    from y in x.DefaultIfEmpty(new PermissionOverridesByUsers())
    select new RolePermissionViewModel
    {
        id = q1.id,
        Name = q1.Name,
        IsSet = ((y.id != null && y.id > 0) ? false : true)
    }).ToList();