【问题标题】:Linq-to-SQL: Ignore null parameters from WHERE clauseLinq-to-SQL:忽略 WHERE 子句中的空参数
【发布时间】:2010-03-26 13:50:40
【问题描述】:

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

    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 表达式?

【问题讨论】:

  • 看起来不错。它在抱怨的一定是c.OwnerUserId。你能确认一下吗?
  • 我已将子句更改为 ( c.OwnerUserId.HasValue &amp;&amp; ownerUserId.HasValue &amp;&amp; c.OwnerUserId.Value == ownerUserId.Value ) 进行测试,但我仍然看到相同的错误消息
  • 任何c.OwnerGroupId 可以为空,从而抛出异常吗?
  • 看起来这个问题比我最初想象的要复杂:peetbrits.wordpress.com/2008/10/18/linq-breaking-your-logic

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


【解决方案1】:

您的问题是您没有传入可空的 int,而是传入了空值。

试试这个:

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 可能为 null 并且在 c.OwnerUserId.Value 中没有任何值

    【讨论】:

    • +1。另外:因此,如果您查询 userId=3 并且某些联系人没有 userId,您将执行(!ownerUserId.HasValue || c.OwnerUserId.Value == ownerUserId.Value) = (!{3}.HasValue || c.{null}.Value == {3}.Value),并且访问{null}.Value 会引发异常。
    • 好点,我没有考虑 - 但是我将子句更改为 ( c.OwnerUserId.HasValue &amp;&amp; ownerUserId.HasValue &amp;&amp; c.OwnerUserId.Value == ownerUserId.Value ) 进行测试,但仍然看到相同的错误消息
    【解决方案3】:

    如果有条件地将 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();
        }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2020-12-28
        • 1970-01-01
        • 1970-01-01
        • 2015-02-24
        • 1970-01-01
        • 2017-05-31
        • 2015-08-29
        • 1970-01-01
        • 2011-01-25
        相关资源
        最近更新 更多