2010-03-26 11 views
3

이 쿼리는 다음 중 하나가 ownerGroupIds 또는 일치하는 ownerUserId 공급 일치하는 ID가 레코드를 반환해야하는 위치에서 널 (null) 매개 변수를 무시합니다. 그러나 ownerUserId이 null 인 경우 쿼리의이 부분을 무시하고 싶습니다. 나는이 경우에 람다 표현식을 사용 할 수있는 따끔 거림을 얻을 Nullable object must have a value.는 Linq에 - 투 - SQL : 절

: 널 (null)이 그 다음 나는 다음과 같은 오류가 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(); 
    } 

?

+1

그것은 바로 보인다. 불만이있는'c.OwnerUserId '여야합니다. 확인 할수 있어요? – Codesleuth

+0

테스트를 위해'(c.OwnerUserId.HasValue && ownerUserId.HasValue && c.OwnerUserId.Value == ownerUserId.Value) '절을 변경했으며 여전히 동일한 오류 메시지가 표시됩니다. –

+0

'c. OwnerGroupId'가 null이되어 Exception을 던집니까? – ANeves

답변

3

귀하의 문제는 당신이 nullable 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와 어떤 연락처가 있습니까? 예인 경우 c.OwnerUserId은 null이 될 수 있으며 아무 값도 가질 수 없습니다. c.OwnerUserId.Value

+1

+1. 또한 userId = 3이고 어떤 연락처에는 userId가 없다면'(! ownerUserId.HasValue || c.OwnerUserId.Value == ownerUserId.Value)'='(! {3} .HasValue || c. {null} .Value == {3} .Value)'를 호출하고'{null} .Value'에 액세스하면 Exception을 던집니다. – ANeves

+0

그러나 내가 고려하지 않은 좋은 점 - \t 나는 테스트를 위해'(c.OwnerUserId.HasValue && ownerUserId.HasValue && ownerUserId.HasValue && c.OwnerUserId.Value == ownerUserId.Value)'절을 변경했고 여전히 같은 것을 보았습니다 에러 메시지 –

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(); 
}