为什么linq-2-sql会创建额外的不必要对象?

我在数据库中有一个简单的Parent Child表

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设计器映射到ParentChild 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(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 

如您所见,为数据库中的每个Child创建了一个Parent对象,最终只能被丢弃。

问题:

  1. 为什么Linq-2-Sql会创建这些不必要的额外Parent对象?
  2. 有没有选项可以避免创建额外的Parent对象?

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

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

如您所见,我们为每个孩子(内部联接)加载一次Parent。 由于身份图,此效果通常不可见。 ORM确保实体对象永远不会被(表,主键)复制。 当您进行更新时,这会派上用场。

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

相同的效果适用于多次返回同一实体的所有查询。