本文介绍了为什么linq-2-sql创建额外的不必要的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在像这样的数据库中有一个简单的父子表

I have a simple Parent Child table in a database like so

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#对象,没有非标准选项.

These tables are mapped to Parent and Child C# objects using the Linq-2-SQL designer in Visual Studio with no non standard options.

我制作了一个简单的测试程序来查询所有孩子及其父母

I made a simple test program to query all child with their parents

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

如您所见,为数据库中的每个Child创建了一个Parent对象,最终最终将其丢弃.

As you can see a Parent object was created for every Child in the database only to be discarded eventually.

问题:

  1. Linq-2-Sql为什么会创建这些不必要的额外Parent对象?
  2. 是否有其他选择可以避免创建额外的Parent对象?
  1. Why does Linq-2-Sql create these unnecessary extra Parent objects ?
  2. Are there any options to avoid creation of extra Parent objects ?

推荐答案

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

This is a side-effect of the way, LoadWith is implemented. LINQ to SQL converts your query internally to:

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

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

As you can see, we are loading the Parent once for every child (an inner join). This effect is not normally visible because of the identity map. ORMs make sure that entity objects are never duplicate by (table, primary key). This comes in handy when you do updates.

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

LINQ to SQL reads the result set returned from the server (it contains the same Parent N times!) and materializes it into objects. Only after materialization is done, the identity map does its job and discards the duplicate parent instances.

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

这篇关于为什么linq-2-sql创建额外的不必要的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 12:13