1

サードパーティのADO.NETプロバイダーを使用してEF4からPostgreSQLを使用しています。私のデータソースには、この結合条件に基づくアイテムに一致するアイテム行がありません。このため、null参照例外に基づいてクエリ1が失敗することを期待しています。ただし、これで完了し、ilの各プロパティの値型のデフォルトが表示されます。item_display_nameは文字列であるため、ilNameはnullに設定されます。ilStartDateはDateTimeのデフォルトに設定されています。x.il.item_idとx.il.item_line_noはどちらも0です。

var query1 =
                    _db.items
                      .GroupJoin(_db.item_line.Where(x => x.start_date == selectedStartDate), x => x.item_id, il => il.item_id, (x, ilgroup) => new { x, ilgroup })
                      .SelectMany(x => x.ilgroup.DefaultIfEmpty(), (x, il) => new { x.x, il })
                      .Select(x =>
                          new
                              {
                                    itemId = x.x.item_id,
                                    ilName = x.il.item_display_name,
                                    ilStartDate = x.il.start_date,
                                    ilItemId = x.il.item_id,
                                    orderLine = x.il.item_line_no});

ただし、Selectの前に結果に対してToArrayを呼び出して強制的に実行すると、null参照例外が発生します。

var query2 =
                _db.items
                    .GroupJoin(_db.item_line.Where(x => x.start_date == selectedStartDate), x => x.item_id, il => il.item_id, (x, ilgroup) => new {x, ilgroup})
                    .SelectMany(x => x.ilgroup.DefaultIfEmpty(), (x, il) => new {x.x, il}).ToArray()
                    .Select(x =>
                            new
                                {
                                    itemId = x.x.item_id,
                                    ilName = x.il.item_display_name,
                                    ilStartDate = x.il.start_date,
                                    ilItemId = x.il.item_id,
                                    orderLine = x.il.item_line_no});

私の理解では、DefaultIfEmptyはそのタイプのデフォルトを返す必要があります。私の型は明らかに参照型ですが、クエリ1が失敗しないのはなぜですか?

4

2 に答える 2

2

これは、最初のクエリが完全にSQLに変換されるためです。nullの「オブジェクト」に関しては、SQLはC#とは異なります。SQLでは、次のようなものを記述してもまったく問題ありません。

SELECT o.Date, ol.Number FROM Order o LEFT JOIN OrderLine ol ON ... (etc.)

がない場合はクラッシュしませOrderOrderLine。ここではnull参照例外はありませんol。SQLはol.Number、順序行が欠落している場合にnull値を出力するだけです。

したがって、最初のステートメントでは、匿名型はSQLから取得した値から直接構築されます。式全体x.il.item_display_nameは、からの出力によって入力されます。DbDataReaderこれは、存在しない場合はnullになりますilgroup

2番目のステートメントでは、最初にオブジェクトの配列がメモリに組み込まれ、xとのilペアで構成され、一部にはないililnull)ものがあります。これで、匿名型がオブジェクト配列から構築され、式は存在しないオブジェクトx.il.item_display_nameから読み取ろうとしitem_display_nameます。

于 2012-10-30T21:53:05.127 に答える
0

これは、EntityFrameworkのトリッキーな特性です。クエリ全体を実行しているときは、実際にデータベースにアクセスすることはありません。EFは、ToArray、ToListなどを実行した場合にのみデータベースに移動します...

最初のクエリでは、ToArray()を最後に配置すると、NullReferenceを取得する必要があります。実際にはToArrayを実行しませんが、ToList()またはToArray()を実行するときに実行するクエリを作成するだけです。

この投稿を見てください:私はデータベースにアクセスしていますか?

于 2012-10-30T20:53:01.090 に答える