2010-03-26 91 views
3

查询下面应该返回,要么在ownerGroupIds或匹配ownerUserId提供一个匹配的ID记录为空参数。但是ownerUserId为空,我希望这部分查询被忽略。LINQ到SQL:忽略来自WHERE子句

public static int NumberUnderReview(int? ownerUserId, List<int> ownerGroupIds) 
    { 
     return (from c in db.Contacts 
       where 
       c.Active == true 
       && 
       c.LastReviewedOn <= DateTime.Now.AddDays(-365) 
       && 
       (// Owned by user 
        !ownerUserId.HasValue || 
        c.OwnerUserId.Value == ownerUserId.Value 
       ) 
       && 
       (// Owned by group 
        ownerGroupIds.Count == 0 || 
        ownerGroupIds.Contains(c.OwnerGroupId.Value) 
       ) 
       select c).Count(); 
    } 

然而,当空传递在ownerUserId然后我得到以下错误:Nullable object must have a value.

我得到一个刺痛我可能会在这种情况下使用lambda表达式?

+1

它看起来正确的。它一定是'c.OwnerUserId'这是抱怨。你可否确认? – Codesleuth 2010-03-26 13:54:44

+0

我已将该子句更改为'(c.OwnerUserId.HasValue && ownerUserId.HasValue && c.OwnerUserId.Value == ownerUserId.Value)'进行测试,而且我仍然看到相同的错误消息 – 2010-03-26 14:05:21

+0

任何'c。 OwnerGroupId'为null,因此抛出异常? – ANeves 2010-03-26 14:10:46

回答

3

你的问题是,你没有通过一个可为空的int,你传递一个null。

试试这个:

Print(null); 

private void Print(int? num) 
{ 
    Console.WriteLine(num.Value); 
} 

,你会得到同样的错误。

如果你这样做它应该工作:

var q = (from c in db.Contacts 
       where 
       c.Active == true 
       && 
       c.LastReviewedOn <= DateTime.Now.AddDays(-365) 
       && 
       (// Owned by group 
        ownerGroupIds.Count == 0 || 
        ownerGroupIds.Contains(c.OwnerGroupId.Value) 
       ) 
       select c); 

if(ownerUserId != null && ownerUserId.HasValue) 
    q = q.Where(p => p.OwnerUserId.Value == ownerUserId.Value); 

return q.Count(); 
2

你与OwnerUserId有一些联系null吗?如果是的话,c.OwnerUserId可能为空并且没有任何值c.OwnerUserId.Value

+1

+1。另外:所以,如果你查询userId = 3并且一些联系人没有userId,你将会执行'(!ownerUserId.HasValue || c.OwnerUserId.Value == ownerUserId.Value)'='(!{3} .HasValue || c。{null} .Value == {3} .Value)',并且访问'{null} .Value'会抛出一个异常。 – ANeves 2010-03-26 14:06:40

+0

好点,我没有考虑 - 但是\t 我改变了条款为'(c.OwnerUserId.HasValue && ownerUserId.HasValue && c.OwnerUserId.Value == ownerUserId.Value)'测试,并仍然看到相同的错误信息 – 2010-03-26 14:10:25

0

如何有条件地将where子句添加到表达式树?

public static int NumberUnderReview(int? ownerUserId, List<int> ownerGroupIds) 
    { 

    var x = (from c in db.Contacts 
       where 
       c.Active == true 
       && 
       c.LastReviewedOn <= DateTime.Now.AddDays(-365) 
       && 
       (// Owned by group 
        ownerGroupIds.Count == 0 || 
        ownerGroupIds.Contains(c.OwnerGroupId.Value) 
       ) 
       select c); 

    if (ownerUserId.HasValue) { 
     x = from a in x 
      where c.OwnerUserId.Value == ownerUserId.Value 
    } 

    return x.Count(); 
    } 
0

问题: “& &” 和 “||”转换为“AndCondition(a,b)”方法,所以“!a.HasValue || a.Value == b”变成了“OrCondition(!a.HasValue,a.Value == b);”这样做的原因可能是得到一个通用的解决方案,可以用于代码和SQL语句。相反,使用“?:”符号。

如需更多信息,请参见我的博客文章:http://peetbrits.wordpress.com/2008/10/18/linq-breaking-your-logic/

// New revised code. 
public static int NumberUnderReview(int? ownerUserId, List<int> ownerGroupIds) 
{ 
    return (from c in db.Contacts 
      where 
      c.Active == true 
      && 
      c.LastReviewedOn <= DateTime.Now.AddDays(-365) 
      && 
      (// Owned by user 
       // !ownerUserId.HasValue || 
       // c.OwnerUserId.Value == ownerUserId.Value 
       ownerUserId.HasValue ? c.OwnerUserId.Value == ownerUserId.Value : true 
      ) 
      && 
      (// Owned by group 
       // ownerGroupIds.Count == 0 || 
       // ownerGroupIds.Contains(c.OwnerGroupId.Value) 
       ownerGroupIds.Count != 0 ? ownerGroupIds.Contains(c.OwnerGroupId.Value) : true 
      ) 
      select c).Count(); 
}