为什么LINQ-2-SQL创建额外的不必要的对象?(Why does linq-2-sql crea

2019-09-21 07:11发布

我有一个简单的亲子表像这样一个数据库

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

这些表映射到ParentChild使用Visual Studio中的LINQ 2 SQL设计师没有非标准选项C#对象。

我做了一个简单的测试程序来查询与父母所有子

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对象?

Answer 1:

这是方式的副作用, LoadWith实现。 LINQ to SQL的内部转换查询到:

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

正如你所看到的,我们正在加载的家长曾经为每一个孩子(一个内部连接)。 这种效果是因为身份的地图通常不可见。 奥姆斯确保实体对象永远不会被(表,主键)复制。 这是在方便的时候你做更新。

LINQ to SQL的读取从服务器(包含同一母体N倍!)返回的结果集,并将其物化为对象。 物化完成后,才,身份映射,它的工作,并丢弃重复父实例。

同样的效应对于同一实体多次返回所有查询。



文章来源: Why does linq-2-sql create extra unnecessary objects?