Asignación de Dapper Query a una colección de objetos (que a su vez tiene un par de colecciones)

dapper multi-mapping

Pregunta

Quiero ejecutar una única consulta (o proceso almacenado con múltiples conjuntos de resultados). Sé cómo hacer Multi-mapping usando Dapper, pero no puedo ordenar cómo mapear las dos colecciones en el mismo padre. Básicamente, dada esta definición de objeto ...

class ParentObject
{
    string Name { get; set; }
    ICollection<ChildObjectOne> ChildSetOne {get;set;}
    ICollection<ChildObjectTwo> ChildSetTwo { get; set; }
}

class ChildObjectOne
{
    string Name { get; set; }
}

class ChildObjectTwo
{
    int id { get; set; }
    string LocationName { get; set; }
}

Quiero poder ejecutar una consulta Dapper que de alguna manera produzca:

IQueryable<ParentObject> result = cnn.Query(
          // Some really awesome dapper syntax goes here
);

Respuesta aceptada

No estoy seguro de si NO QUIERE usar MultiMapping, pero así es cómo funcionaría para su caso. Por lo que sé y leo en SO, no es posible mapear un gráfico de objetos anidados con una simple Query .

 static void Main(string[] args)
        {
            var sqlParent = "SELECT parentId as Id FROM ParentTable WHERE parentId=1;";
            var sqlChildOneSet = "SELECT Name FROM ChildOneTable;"; // Add an appropriate WHERE
            var sqlChildTwoSet = "SELECT Id, LocationName FROM ChildTwoTable;"; // Add an appropriate WHERE

            var conn = GetConnection() // whatever you're getting connections with
            using (conn)
            {
                conn.Open();
                using (var multi = conn.QueryMultiple(sqlParent + sqlChildOneSet + sqlChildTwoSet))
                {
                    var parent = multi.Read<ParentObject>().First();
                    parent.ChildSetOne = multi.Read<ChildOne>().ToList();
                    parent.ChildSetTwo = multi.Read<ChildTwo>().ToList();
                }
            }
        }

Preguntas similares para objetos anidados y dapper:

https://stackoverflow.com/search?q=nested+objects+%2B+dapper


Respuesta popular

Es posible materializar un objeto con relaciones de uno a muchos utilizando IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map); método en este caso. Sin embargo, debe realizar algunos cambios en las entidades para tener suficiente información para hacerlo.

Aquí hay algunos hilos SO con preguntas similares.

¿Cómo mapeo listas de objetos anidados con Dapper?

Función de extensión para hacerlo más limpio

Dapper.Net por ejemplo - Mapeo de relaciones

public class ParentObject
{
    public ParentObject()
    {
        ChildSetOne = new List<ChildObjectOne>();
        ChildSetTwo = new List<ChildObjectTwo>();
    }
    // 1) Although its possible to do this without this Id property, For sanity it is advisable.
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<ChildObjectOne> ChildSetOne {get; private set;}
    public ICollection<ChildObjectTwo> ChildSetTwo { get; private set; }
}

public class ChildObjectOne
{
    // 2a) Need a ParentId
    public int ParentId { get; set; }
    public string Name { get; set; }
}

public class ChildObjectTwo
{
    // 2b) This ParentId is not required but again for sanity it is advisable to include it.
    public int ParentId { get; set; }
    public int id { get; set; }
    public string LocationName { get; set; }
}

public class Repository
{
    public IEnumerable<ParentObject> Get()
    {
        string sql = 
            @"SELECT 
                p.Id, 
                p.Name, 
                o.Name, 
                o.ParentId, 
                t.Id, 
                t.LocationName, 
                t.ParentId 
            FROM 
                Parent p 
                    LEFT JOIN ChildOne o on o.ParentId = p.Id 
                    LEFT JOIN ChildTwo t on t.ParentId = p.Id 
            WHERE 
                p.Name LIKE '%Something%'";

        var lookup = new Dictionary<int, ParentObject>();
        using (var connection = CreateConnection())
        {

            connection.Query<ParentObject, ChildObjectOne, ChildObjectTwo, ParentObject>(
                sql, (parent, childOne, childTwo) =>
                {
                    ParentObject activeParent;

                    if (!lookup.TryGetValue(childOne.ParentId, out activeParent)) 
                    {
                        activeParent = parent;
                        lookup.add(activeParent.Id, activeParent);
                    }

                    //TODO: if you need to check for duplicates or null do so here
                    activeParent.ChildSetOne.Add(childOne);

                    //TODO: if you need to check for duplicates or null do so here
                    activeParent.ChildSetTwo.Add(childTwo);

                });   
        }
        return lookup.Values;
    }
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué