2010-03-26 424 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(); 
}