2012-08-16 10 views
14

Tengo una sencilla tabla de niño de los padres en una base de datos como tal¿Por qué linq-2-sql crea objetos adicionales innecesarios?

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]) 

Los datos que tengo en ellos se

tabla primaria

Id Name 
1 John 

tabla secundaria

Id ParentId Name 
1  1 Mike 
2  1 Jake 
3  1 Sue 
4  1 Liz 

Estas tablas están asignadas a los objetos Parent y Child C# utilizando el diseñador Linq-2-SQL en Visual Studio sin opciones no estándar.

Hice un programa de prueba sencilla para realizar consultas de todo niño con sus padres

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

      } 
     } 
    } 
} 

La salida del programa anterior es

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 

Como se puede ver un objeto Parent fue creado para cada Child en la base de datos solo para descartar eventualmente.

Preguntas:

  1. ¿Por qué LINQ-2-SQL crean estos objetos innecesarios Parent adicionales?
  2. ¿Hay alguna opción para evitar la creación de objetos extra Parent?
+0

No crea objetos singleton como está esperando y tampoco debería hacerlo. ¿Qué pasaría si tuviera una consulta que seleccionó un objeto y comienza a escribir una consulta de actualización en la misma identificación? ¿Debería ver inmediatamente los resultados del cambio antes de enviar los cambios? Se crea una instancia única para cada consulta. –

+0

@JeffMercado, no: L2S solo entrega una instancia por tabla y clave. Esta es una característica importante de los ORM (mapa de identidad). – usr

Respuesta

12

Esto es un efecto secundario del camino, se implementa LoadWith. LINQ a SQL convierte su consulta internamente para:

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

Como se puede ver, estamos cargando el Padre una vez para todos los niños (una combinación interna). Este efecto no es normalmente visible debido al mapa de identidad. Los ORM se aseguran de que los objetos de la entidad nunca sean duplicados por (tabla, clave principal). Esto es útil cuando haces actualizaciones.

LINQ to SQL lee el conjunto de resultados devuelto por el servidor (contiene el mismo Parent N veces) y lo materializa en objetos. Solo después de que se realiza la materialización, el mapa de identidad hace su trabajo y descarta las instancias padre duplicadas.

El mismo efecto funciona para todas las consultas que devuelven la misma entidad varias veces.

+3

Exactamente es una unión interna. Es como escribir esta consulta y ejecutar en SSMS. SELECT * FROM child JOIN parent en child.ParentId = Parent.Id ... cuando ejecuta esta consulta, obtiene el id. Principal para cada hijo nada nuevo, de hecho aquí VS sigue los pasos estándar del estándar SQL. – MStp

Cuestiones relacionadas