6

EntityFrameworkモデルに奇妙な動作が見られます。次のようなクエリがあります。

var rows = ( from alarm in context.Alarms
             join temp  in context.ListDetails on alarm.ListDetailId equals  temp.ListDetailId into entries from entry in entries.DefaultIfEmpty()
             join read  in context.Reads       on alarm.ReadId       equals  read.ReadId
             join plate in context.Images      on alarm.ReadId       equals plate.ReadId
             where alarm.IActive == 1 && ! alarm.TransmittedAlarm 
             where  read.IActive == 1 
             where plate.IActive == 1 && plate.ImageTypeId == 2
             select new { alarm, entry, read, plate } ).ToArray();

クエリは、列名のアルファベット順にすべての列を返します。結果セットのいくつかの行では、この列がNULLであることがわかります。デバッガーでrows変数を展開すると、行全体がnullであることがわかります。

編集:いくつかの説明。

「最初の列」とは、最初の行の最初の列を意味します。つまり、「SELECT A、B、C FROM ...」では、Aを意味します。EntityFrameworkが構築するクエリがすべての結合された結果セットの列はアルファベット順に、最初の列はアルファベット順にnull可能であり、一部の行ではnullです。

問題の列は主キーではありません。主キーの場合、nullにすることはできません。

Entity Frameworkは、返されたデータの行をオブジェクトに処理するときに、各行の最初の列の値を調べます。その列がnullの場合、その列に対応するプロパティがnullに設定されているオブジェクトではなく、行に対してnullが返されます。

これは特に左外側の結合とは何の関係もないと思います。私のクエリがそれを使用しているのはたまたまです。ただし、これを検証するためのテストは行っていないので、これは単なる仮定です。

誰かがこれを見たことがありますか?誰かがこれを修正していますか?

トニー

4

2 に答える 2

6

私はまったく同じ問題を抱えていることを確認できます.EFによって形成されたSQLクエリnullが結果の最初の列にある場合、エンティティではなくnullを返します。それはまさに次のことを意味します:

using (var dc = new MyDbContext())
{
    var q = dc.Lands; //Lands is DbSet<Land>
    q = q.Where(criteria); //this leads to SQL query returning null in first column, confirmed by profiler
    var t = q.Single(); //t is now null
}

null別の基準を取ると、最初の列にならないのtは通常の非null実体です。

EFのある種のあいまいな動作/バグであるように私には思えます。

アップデート

数時間の調査の後、次の動作が見つかりました。EF は、結果の最初の列にあるnullエンティティを返しNULLますが (これは予想される動作を中断します)、選択リストの最初に配置する列についていくつかの概念があります。したがって、モデルをデータベースの状態と正確に一致させた後 (つまり、すべてのデータベース列を示し、ナビゲーション プロパティをNULLABLEに置き換えます) - Code First を使用しているため、データベースについて明示する場所がたくさんあります-それを機能させます。requiredoptional

これは、モデルの店舗レベルの定義をデータベースに対してチェックする必要があることを意味します (使用するパラダイム、デザイナー ベース、またはコード ベースに応じて、異なる場所になります)。

于 2012-06-14T18:19:07.747 に答える
1

参加に使用DefaultIfEmptyします。その意味は

entries結合基準()に一致する項目がない場合は、タイプ()alarm.ListDetailId equals temp.ListDetailIdの単一のデフォルト値をに入れてください。ListDetailnullentries

この場合、EFはを生成しLEFT JOINます。実際、このコードは、LEFT JOINLinq2SqlまたはEFを使用してを生成するためのよく知られた方法です。

テーブル内のどの行も基準に一致しない場合、LEFT JOINステートメントNULLはテーブルのすべての列の値を選択します。JOIN実際、重要な列はエンティティのPK列だけです。EFは、PK値がNULLであるかどうかを確認し、エンティティが存在しないと判断して、に入れnullますentries。次に、これを結果のプロパティ値として取得しますnullentry

于 2012-04-18T16:19:18.737 に答える