2011-05-27 18 views
15

Digamos que tengo una serie de objetos que forman un agregado.¿Cómo selecciono un objeto agregado de manera eficiente usando Dapper?

public class C{ 
public string Details {get;set;} 
} 

public class B{ 
    public string Details {get;set;} 
    public List<C> Items {get;set;} 
} 

public class A{ 
    public long ID {get;set;} 
    public string Details {get;set;} 
    public List<B> Items {get;set;} 
} 

usando Dapper, ¿cuál es la mejor manera de poblar estos de tablas en una base de datos (en mi caso es postgres pero eso no debe importar). Las tablas en el ejemplo son prácticamente una a una con el modelo de objetos. La propiedad Items en la clase que representa relaciones de clave foránea con cada objeto subordinado. es decir, 3 mesas, A tiene una relación de uno a muchos con B, B tiene una relación de uno a muchos con C.

Así que para un determinado ID de A Quiero que mis objetos para tener todos sus datos secundarios también.

Mi mejor suposición es que debería usar QueryMultiple de alguna manera, pero no estoy seguro de cómo hacerlo.

+0

¿Quizás el método 'QueryMultiple'? Acabo de descargar dapper ... suponiendo que te refieras a 'dapper-dot-net'. – IAbstract

+0

yep dapper-dot-net es con lo que estoy experimentando. – Peter

+0

Lo que estoy haciendo actualmente es un QueryMultiple sobre todas las tablas diferentes y luego usando linq para asignar por id a las colecciones secundarias. significa que hago un lote en la base de datos y hago todo el trabajo en ram en lugar de lo que he visto hacer en linq2sql, que es un cobertizo de consultas incidentales al DB ... Estoy muy contento con el resultado que acabo se preguntó si mi enfoque era/es la intención del autor apuesto. – Peter

Respuesta

11

Creo que el asistente que propongo aquí: Multi-Mapper to create object hierarchy puede ser de ayuda.

var mapped = cnn.QueryMultiple(sql) 
    .Map<A,B,A> 
    (
     A => A.ID, 
     B => B.AID, 
     a, bees => { A.Items = bees}; 
    ); 

Asumiendo que extiende su GridReader y con un mapeador:

public static IEnumerable<TFirst> Map<TFirst, TSecond, TKey> 
    (
    this GridReader reader, 
    Func<TFirst, TKey> firstKey, 
    Func<TSecond, TKey> secondKey, 
    Action<TFirst, IEnumerable<TSecond>> addChildren 
    ) 
{ 
    var first = reader.Read<TFirst>().ToList(); 
    var childMap = reader 
     .Read<TSecond>() 
     .GroupBy(s => secondKey(s)) 
     .ToDictionary(g => g.Key, g => g.AsEnumerable()); 

    foreach (var item in first) 
    { 
     IEnumerable<TSecond> children; 
     if(childMap.TryGetValue(firstKey(item), out children)) 
     { 
      addChildren(item,children); 
     } 
    } 

    return first; 
} 

Se podría ampliar este patrón para trabajar con una jerarquía de 3 niveles.

+0

Esta es una buena solución, gracias – Peter

+1

Esto no funciona para mí. Cuando intenta leer TSecond, el lector se ha consumido y no se puede volver a leer. –

+0

@Mr Grok - yo también. ¿Ha encontrado una solución para esto? – BZink

Cuestiones relacionadas