2011-02-10 3 views
11

を使用する場合はNULL可能int型変数、正確な結果を使用している場合0結果を返す「NullableInt」(null許容INTタイプ) :それは「ヌル」LINQレコード</p> <p>をしている、私は1列が「テスト」と呼ばれるテーブルを有し、「NULL」

と比較されている場合だけトンのように、ヌルの値を持つ「nullableInt」変数を、使用していてもカントー1、2、何らかの理由でヌル

int? nullableInt = null; 
var t = db.tests.Where(x => x.NullableInt == null).ToList(); // returns 1 record 
var t2 = db.tests.Where(x => x.NullableInt == nullableInt).ToList(); // returns 0 records 

は、t2は、0のレコードを返します

ご協力いただければ幸いです!

答えて

2

クエリは、この方法で構築することができます常に小さな注意点とはいえ、動作する別の解決策は、

var q = db.tests; 
if(nullableInt.HasValue) 
{ 
    q = q.Where(x => x.NullableInt == nullableInt.Value); 
} 
else 
{ 
    q = q.Where(x => x.NullableInt == null); 
} 
var t2 = q.ToList(); 
+0

+1それは厄介ですが、それはそれが見える唯一の方法です=( – Francisco

+0

私の答えはEF6で修正されており、EF5での修正に同意することができます –

6

はい、LINQ-to-SQL/Entity Frameworkのバグです。 IS NULLクエリは、nullになる可能性のある変数ではなく、nullをクエリにハードコードする場合にのみ生成されます。

2番目のクエリは、最初は、WHERE句に適切なIS NULLを生成する

SELECT ....... 
WHERE NullableInt == @someParam 
WHERE @someParam is null. 

を生成します。

LINQ-to-SQLを使用している場合は、Console.Outにクエリを記録してEFを使用している場合は、ToTraceString()で同じ情報(またはSQLサーバープロファイラー)

+2

実際には、2番目の式 'nullableInt'は' nullableInt = null'でその値を代入しても 'nullable'ではないので、バグだとは思わない(値がnullでない構造体なので) 。したがって、フレームワークは他の構造体(intなど)と同じように扱います。 –

+2

@Danny、それは裂ける毛です。バグは、たとえコードが仕様書が行うべきことを正確に示しているとしても、仕様に含まれる可能性があります。言い換えれば、ここでのバグは、コードが何か間違ったことを起こすのではなく、誰かがこのシナリオを考慮しなかったことではないかもしれません。 –

+1

実際に髪を分ける。 EFパーサが2番目のクエリをIS NULL以外のものとして生成する必要がある正当な理由はありません。そして、私は手元にそのリンクを持っていませんが、これはMSのバグとして非常に高い投票数で記録されています。 –

0

あり:

int? nullableInt = null; 
var t2 = db.tests.Where(x => object.Equals(x.NullableInt, nullableInt)).ToList(); 

値がnull yのとき

SELECT ... 
WHERE ([t0].[NullableInt] IS NOT NULL) AND ([t0].[NullableInt] = @p0) 

明らかにそれは余分な条件(種類の不可解されたソースを)持っています。ouしかし、あなたのようなものが得られますときにnullではない、適切なIS NULLクエリを取得します。つまり、SQL Serverのクエリオプティマイザは、@ p0がnull以外の値であるため、最初の条件はスーパーセットであり、where句を削除します。

+0

LINQ-to-SQLテストしていませんが、EF4では絶対に動作しません)。同じold = @paramを生成します。@paramはnullに設定されます。 –

+0

ああ、彼らはそれを "固定"しました。はい、L2Sで動作します。 – mmix

0

うやって:

var t2 = db.tests.Where(x => x.NullableInt == nullableInt ?? null).ToList(); 

仕事を?

しかし、まったくの狂気のようです。

+0

本当に狂っていて、うまくいきません。私は生成されたSQlを入れようとしましたが、失敗し続けます - 何らかの注射攻撃に対して防御していると推測しています –

2

TL; DRあなたはEF6でDbContextを使用している場合、これは固定されている

EF5(またはEF6でObjectContext)を使用している場合は、ObjectContext.ContextOptions.UseCSharpNullComparisonBehaviorをtrueに設定する必要があります。 DbContextでこれを行うには、次のようにしてください:

詳細

この問題の根本的な原因は、データベースがNULL値とどのようにC#はNULL値を比較する比較方法の違いです。あなたはC#でセマンティクスを使いたいと思っています。

EF5では、ObjectContext.ContextOptions.UseCSharpNullComparisonBehaviorを導入しました。これにより、データベースセマンティクスの代わりにC#セマンティクスを使用することができました。デフォルトはfalseです(EF5にアップグレードすると、既存のクエリが魔法のように異なる結果を返すことはありません)。しかし、これをtrueに設定すると、両方のクエリで行が返されます。

あなたがそれを設定するのObjectContextに落下する必要がEF5でDbContextを使用している場合:

((IObjectContextAdapter)db).ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior = true; 

をあなたはEF6を使用している場合は行ってもいいですので、それはすでにDbContextにtrueに設定されています。これにより、既存のクエリに潜在的な影響を及ぼすほどの混乱が生じることが判明しました。

+0

Rowanに感謝します。これは非常に役に立ちました。 – Eric

関連する問題

 関連する問題