2010-12-15 22 views
11

に私はこのような方法でクエリがあります:SQL試行へのLINQ:実行時に"Nullableオブジェクトには値が必要です。" LINQのからSQLへの

public IList<BusinessObject> GetBusinessObject(Guid? filterId) 
{ 
    using (var db = new L2SDataContext()) 
    { 
     var result = from bo in db.BusinessObjects 
        where (filterId.HasValue) 
           ? bo.Filter == filterId.value 
           : true 
        orderby bo.Name 
        select SqlModelConverters.ConvertBusinessObject(bo); 
     return result.ToList(); 
    } 
} 

を、これはデバッガを見てSystem.InvalidOperationException: Nullable object must have a value.

をスローし、問題は私のWhere句であります全体をSQLに変換するため、filterIdがNULLの場合でもfilterId.valueにアクセスしようとします。

C#コンパイラ/ CLRがwhere句をコードブロックとして評価し、Linq To SQLに2つのブランチの1つのみを送信すると思っていましたが、それは動作しません。私のリファクタリングバージョンは動作しますが、非常にエレガントではありません

は:

public IList<BusinessObject> GetBusinessObject(Guid? filterId) 
{ 
    using (var db = new L2SDataContext()) 
    { 
     var temp = from bo in db.BusinessObjects select bo; 
     if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value); 
     var result = from t in temp 
        orderby t.Name 
        select SqlModelConverters.ConvertBusinessObject(bo); 
     return result.ToList(); 
    } 
} 

私はそれがないで怠惰な評価が一つだけのクエリが実際に送られていることを確認しますが、その一時オブジェクトを持つことがわかっています本当に素晴らしい。

答えて

16

あなたがしようとしました:

where filterId == null || t.Filter == filterId 
+1

すごいああ、それは完璧に動作します!わずかに読めない3次演算子を使用しないようにしてくれますし、filterIdだけでなくfilterId.Valueに不必要にアクセスしたことによる実際の例外を解決します。 –

1

修正内容は正確です。関数の入力に基づいて、動的に問合せを構築しようとしています。とにかくWHERE TRUEを指定するのではなく、where句を省略することをお勧めします。私がこの質問を書いていたら、私はあなたの固定版を自分で使うつもりです。

言語キーワードを使用するほど美味しくはありませんが、私の意見では依然としてクエリにアプローチするのは正しい方法です。

関連する問題