Linq-to-SQL:忽略WHERE子句中的空参数

时间:2010-03-26 13:50:40

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

以下查询应返回在 ownerGroupIds 中提供匹配ID或与 ownerUserId 匹配的记录。但是 ownerUserId 为空,我希望忽略此部分查询。

    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 传入null时,我会收到以下错误:Nullable object must have a value.

我感到刺痛我可能不得不在这个实例中使用lambda表达式?

4 个答案:

答案 0 :(得分: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();

答案 1 :(得分:2)

您是否与OwnerUserId建立了联系?如果是,c.OwnerUserId可能为空且在c.OwnerUserId.Value

中没有任何值

答案 2 :(得分: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();
    }

答案 3 :(得分:0)

问题:“&amp;&amp;”和“||”被转换为像“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();
}