14

私はそのようなデータベースに単純な親子テーブルを持っています

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デザイナーを使用してC#オブジェクトParentにマップされます。Child

私は簡単なテストプログラムを作成して、すべての子供を両親と一緒に照会しました

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()));

            }
        }
    }
}

上記のプログラムの出力は次のとおりです。

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

ご覧のとおり、ParentオブジェクトはChildデータベース内のすべてに対して作成され、最終的には破棄されます。

質問:

  1. Linq-2-Sqlがこれらの不要な余分なParentオブジェクトを作成するのはなぜですか?
  2. Parent余分なオブジェクトの作成を回避するためのオプションはありますか?
4

1 に答える 1

13

LoadWithこれは、実装方法の副作用です。LINQ to SQLは、クエリを内部的に次のように変換します。

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

ご覧のとおり、すべての子に対して1回親をロードしています(内部結合)。IDマップのため、この効果は通常は表示されません。ORMは、エンティティオブジェクトが(テーブル、主キー)によって複製されないようにします。これは、更新を行うときに便利です。

LINQ to SQLは、サーバーから返された結果セットを読み取り(同じ親がN回含まれています!)、それをオブジェクトに実体化します。マテリアライゼーションが実行された後でのみ、IDマップはその役割を果たし、重複する親インスタンスを破棄します。

同じ効果は、同じエンティティを複数回返すすべてのクエリに対して機能します。

于 2012-08-20T21:14:59.563 に答える