9

今日の物議を醸しているブログ投稿で、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 から期待されるようには動作しません。

では、これは良いフレームワーク設計ですか? それとも、マイクロソフトは私たちのためにこれを考えすぎているのでしょうか?

4

6 に答える 6

12

ジョン、

私はエンティティへのlinqでも遊んでいます。linq to SQL に追いつくまでには長い道のりがあります。Type Inheritance ごとのテーブルのエンティティに linq を使用する必要がありました。最近、1 社 2 種類の ORM テクノロジ全体を説明している良い記事を見つけまし

ただし、次のようにすることで、ある意味で遅延読み込みを行うことができます。

// Lazy Load Orders 
var alice2 = data.Customers.First(c => c.Name == "Alice");

// Should Load the Orders
if (!alice2.Orders.IsLoaded)
    alice2.Orders.Load();

または、元のクエリに Orders を含めることもできます。

// Include Orders in original query
var alice = data.Customers.Include("Orders").First(c => c.Name == "Alice");

// Should already be loaded
if (!alice.Orders.IsLoaded)
    alice.Orders.Load();

それが役に立てば幸い。

デイブ

于 2008-12-18T15:39:16.203 に答える
5

では、これは良いフレームワーク設計ですか? それとも、マイクロソフトは私たちのためにこれを考えすぎているのでしょうか?

それを分析してみましょう - Microsoft が行っているすべての考え方によって、私たちは怠惰なプログラマーになる必要はありません。しかし、一般的に、それは私たちの生産性を高めます (ほとんどの場合)。彼らは考えすぎなのか、それとも単に私たちのこと考えているだけなのか?

于 2008-12-03T22:48:52.083 に答える
2

LINQ-to-Sql と LINQ-to-Entities が 2 つの異なる会社から提供されたものである場合、それは許容できる違いです。すべての LINQ-To-Whatevers を同じ方法で実装する必要があるという法律はありません。

ただし、どちらも Microsoft から提供されています。一見するとまったく同じに見える 2 つの異なるものを使用する方法を知るために、社内の開発チームやプロセスに関する詳細な知識は必要ありません

ORM には役割があり、物事を成し遂げようとする人々のギャップを実際に埋めますが、ORM の使用者は、ORM が物事を成し遂げる方法を正確に知っている必要があります。

于 2008-12-03T22:43:28.490 に答える
2

この問題で数日を失った私は、同情します。

「欠点」があるとすれば、抽象化のレイヤーがこの種の問題から隔離されると期待する合理的な傾向があることです。LINQ からエンティティ、データベース レイヤーへと、2 重に移行します。

たとえば、MS-SQL (LingToSQL を使用) から MySQL (LinqToEntities を使用) に切り替えなければならない場合、少なくとも LINQ は、プログラムを書き直さなければならないコストを節約するだけでなく、同じであると考えられます。論理。

内部の永続化メカニズムが変更されたという理由だけで、.Load() や .Include() を使用して LINQ を使用してコードを散らかさなければならないことは、特にサイレント エラーの場合、少し気がかりに思えます。LINQ レイヤーは、少なくとも一貫して動作する必要があります。

多くの ORM フレームワークは、単に null を返すのではなく、プロキシ オブジェクトを使用して遅延オブジェクトを透過的に動的に読み込みます。

私は、彼らがあなたの利益のために故意にやったという言い訳を受け入れない傾向があります。他の ORM フレームワークでは、必要に応じて熱心な読み込みと遅延読み込みのどちらが必要かについて注釈を付けることができます。ここでも同じことができます。

于 2010-02-26T17:17:23.220 に答える
1

私は ORM についてあまり知りませんが、LinqToSql と LinqToEntities のユーザーとして、Alice の Orders をクエリしようとすると、linq クエリを作成するときに追加のクエリが実行されることを願っています (何もクエリを実行したり、行ごとにすべてを照会します)。

期待するのは当然のようです

from o in alice.Orders where o.Item == "Item_Name" select o

それが、人々が最初に ORM を使用する理由の 1 つです (データ アクセスを簡素化するため)。

LinqToEntities について読めば読むほど、LinqToSql はほとんどの開発者のニーズを適切に満たしていると思います。通常、テーブルの 1 対 1 のマッピングが必要です。

于 2008-12-03T22:37:30.780 に答える
1

Microsoft の内部開発チームとプロセスについて知る必要はありませんが、実際には、これら 2 つのテクノロジはまったく異なる 2 つの獣です。

LINQ to SQL の設計上の決定は、簡単にするために、コレクションを暗黙的に遅延読み込みすることでした。ADO.NET Entity Framework チームは、ユーザーが知らないうちにクエリを実行したくなかったため、最初のリリースで明示的に読み込まれるように API を設計しました

LINQ to SQL は ADO.NET チームに引き渡されたため、将来的に API が統合されるか、LINQ to SQL が Entity Framework に組み込まれるか、LINQ to SQL が無視されて萎縮し、最終的に非推奨になる可能性があります。 .

于 2008-12-09T22:01:29.630 に答える