今日の物議を醸しているブログ投稿で、Hackification は、新しい LINQ To Entities フレームワークのバグと思われるものについて次のように主張しています。
顧客を検索するとします。
var alice = data.Customers.First( c => c.Name == "Alice" );
うまくいきました。それでは、彼女の注文の 1 つを見つけることができるかどうか見てみましょう。
var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();
LINQ-to-SQL は子行を見つけます。LINQ-to-Entities は黙って何も返しません。
ここで、データベース内のすべての注文を反復処理するとします。
foreach( var order in data.Orders ) { Console.WriteLine( "Order: " + order.Item ); }
そして今、私の検索を繰り返します:
var order = ( from o in alice.Orders where o.Item == "Item_Name" select o ).FirstOrDefault();
わお!LINQ-to-Entities は、子オブジェクトが存在しないことを以前に伝えていたにもかかわらず、突然、子オブジェクトが存在することを伝えています。
私の最初の反応は、これはバグでなければならないというものでしたが、さらに検討した後 (そしてADO.NET チームによってバックアップされた後)、この動作は、Alice がプルされたときに Entity Framework が Orders サブクエリを遅延読み込みしないことが原因であることに気付きました。データコンテキスト。
これは、 order が LINQ-To-Object クエリであるためです。
var order = ( from o in alice.Orders
where o.Item == "Item_Name"
select o ).FirstOrDefault();
そして、彼のforeachループ中は、データコンテキストにアクセスしていません:
foreach( var order in data.Orders )
データコンテキストにアクセスしています。
LINQ-To-SQL は Orders の遅延読み込みプロパティを実際に作成したため、アクセスすると別のクエリが実行され、LINQ to Entities は関連データを手動で取得する必要があります。
さて、私は ORM の大ファンではありません。これがまさにその理由です。必要なすべてのデータを手元に用意するために、背後でクエリを繰り返し実行することがわかりました。たとえば、上記の linq-to-sql クエリは、顧客の行ごとに追加のクエリを実行して注文を取得する場合があります。 .
ただし、これを行わない EF は、最小の驚きの原則に大きく違反しているようです。これは技術的には正しい方法ですが (注文を取得するために 2 番目のクエリを実行するか、ビューからすべてを取得する必要があります)、ORM から期待されるようには動作しません。
では、これは良いフレームワーク設計ですか? それとも、マイクロソフトは私たちのためにこれを考えすぎているのでしょうか?