2012-08-16 4 views
14

そうなぜlinq-2-sqlは不要な不要なオブジェクトを作成しますか?

CREATE TABLE [Parent](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](256) NOT NULL)  
ALTER TABLE [Parent] ADD CONSTRAINT [PK_Parent_Id] PRIMARY KEY ([Id])  

CREATE TABLE [Child](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [ParentId] [int] NOT NULL, 
    [Name] [nvarchar](256) NOT NULL)  
ALTER TABLE [Child] ADD CONSTRAINT [PK_Child_Id] PRIMARY KEY ([Id]) 
ALTER TABLE [Child] ADD CONSTRAINT [FK_Child_Parent_ID] 
    FOREIGN KEY([ParentId]) REFERENCES [Parent] ([Id]) 

私はそれらを持っているデータは

親表

Id Name 
1 John 

子テーブル

であるように、私は、データベースに簡単な親子テーブルを持っています
Id ParentId Name 
1  1 Mike 
2  1 Jake 
3  1 Sue 
4  1 Liz 

Visual StudioのLinq-2-SQLデザイナを標準以外のオプションなしで使用して、これらのテーブルをParentおよびChild C#オブジェクトにマッピングします。

私はあなたがParentオブジェクトはすべてのChildのために作成された見ることができるように、上記のプログラムの出力は

CreatedParent 1 hashcode=53937671 
CreatedParent 2 hashcode=9874138 
CreatedParent 3 hashcode=2186493 
CreatedParent 4 hashcode=22537358 
Parent name=John hashcode=53937671 
Parent name=John hashcode=53937671 
Parent name=John hashcode=53937671 
Parent name=John hashcode=53937671 

ある

public partial class Parent 
{ 
    static int counter = 0; 
    //default OnCreated created by the linq to sql designer 
    partial void OnCreated() 
    { 
     Console.WriteLine(string.Format("CreatedParent {0} hashcode={1}", 
      ++counter , GetHashCode())); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var db = new SimpleDbDataContext()) 
     { 
      DataLoadOptions opts = new DataLoadOptions(); 
      opts.LoadWith<Child>(c => c.Parent); 
      db.LoadOptions = opts; 
      var allChildren = db.Childs.ToArray(); 
      foreach (var child in allChildren) 
      { 
       Console.WriteLine(string.Format("Parent name={0} hashcode={1}", 
        child.Parent.Name, child.Parent.GetHashCode())); 

      } 
     } 
    } 
} 

両親とすべての子を照会する簡単なテストプログラムを作りました最終的に捨てられるだけのデータベースに保存されます。

質問:

  1. なぜLINQの-2-SQLは、これらの不要な余分なParentオブジェクトを作成していますか?
  2. 余分なParentオブジェクトの作成を避けるオプションはありますか?
+0

期待しているようにシングルトンオブジェクトを作成しません。 1つのオブジェクトを選択したクエリが1つで、同じIDで更新クエリを書き始めるとどうなりますか?変更を提出する前にすぐに変更の結果を確認する必要がありますか?一意のインスタンスが各クエリに対して作成されます。 –

+0

@JeffMercado、no:L2Sは、テーブルとキーごとに1つのインスタンスのみを渡します。これはORM(アイデンティティマップ)の重要な機能です。 – usr

答えて

12

これは、方法の副作用であり、LoadWithが実装されています。あなたが見ることができるように、我々は(インナー参加)すべての子どものために一度親をロードしている

from c in children 
select { Child = c, Parent = c.Parent } 

:SQLへのLINQは、内部にクエリを変換します。このエフェクトは、アイデンティティマップのために通常は表示されません。 ORMは、エンティティオブジェクトが決して(テーブル、主キー)によって重複しないことを確認します。これは、更新を行うと便利です。

LINQ to SQLは、サーバーから返された結果セットを読み込み(同じParent N回!)、オブジェクトにマテリアライズします。マテリアライゼーションが完了した後でのみ、アイデンティティマップはそのジョブを実行し、複製された親インスタンスを破棄します。

同じエンティティを複数回返すすべてのクエリに対して同じ効果が働きます。

+3

これは正確に内部結合です。これはこのクエリを作成し、SSMSで実行するようなものです。 SELECT * FROM child JOIN parent of child.ParentId = Parent.Id ...この問合せを実行すると、各子の親IDは新しいものはありません。実際には、VSはSQL標準の標準的な踏み台に従っています。 – MStp

関連する問題