Dapper map multiple join Sql Query

c# dapper mapping orm sql

Pregunta

Quiero asignar el objeto complejo al resultado apuesto de la consulta que tiene dos uniones internas. Sé que tenemos una solución para mapear una unión interna, pero quiero mapear el resultado de dos combinaciones internas.

Aquí está el escenario:

Mis clases son:

public class Order 
{
    public int id { get; set; }
    public string order_reference { get; set; }
    public string order_status { get; set; }
    public List<OrderLine> OrderLines { get; set; }
}

public class OrderLine
{
    public int id { get; set; }
    public int order_id { get; set; }
    public string product_number { get; set; }
    public List<OrderLineSize> OrderLineSizes { get; set; }
}

public class OrderLineSize
{
    public int id { get; set; }
    public int order_line_id { get; set; }
    public string size_name { get; set; }
}

Order tiene OrderLines como List y OrderLine como OrderLineSizes como List.

Ahora, aquí está mi consulta base en la que quiero completar List<Order> con los datos correctos:

SELECT *
FROM orders_mstr o
INNER JOIN order_lines ol ON o.id = ol.order_id
INNER JOIN order_line_size_relations ols ON ol.id = ols.order_line_id

Esto es lo que intenté hasta ahora:

var lookup = new Dictionary<int, Order>();
            connection.Query<Order, OrderLine, Order>(@"
                    SELECT o.*, ol.*
                    FROM orders_mstr o
                    INNER JOIN order_lines ol ON o.id = ol.order_id                    
                    ", (o, ol) => {
                    Order orderDetail;
                    if (!lookup.TryGetValue(o.id, out orderDetail))
                    {
                        lookup.Add(o.id, orderDetail = o);
                    }
                    if (orderDetail.OrderLines == null)
                        orderDetail.OrderLines = new List<OrderLine>();
                    orderDetail.OrderLines.Add(ol);
                    return orderDetail;
                }).AsQueryable();

            var resultList = lookup.Values;

Al usar esto, puedo mapear correctamente el objeto de pedido con OrderLine, pero también quiero llenar OrderLineSizes con los datos correctos.

Respuesta popular

No sé qué clase es 'OrderDetail', no lo proporcionas, así que utilicé Order class.
Esto también se puede hacer mediante QueryMultiple, pero debido a que su pregunta incluye INNER JOIN, no la utilizo.

public Dictionary<int, Order> GetOrderLookup()
{
    var lookup = new Dictionary<int, Order>();

    const string sql = @"   SELECT  o.id,
                                    o.order_reference,
                                    o.order_status,

                                    ol.id,
                                    ol.order_id,
                                    ol.product_number,

                                    ols.id,
                                    ols.order_line_id,
                                    ols.size_name
                            FROM    orders_mstr o
                            JOIN    order_lines ol ON o.id = ol.order_id
                            JOIN    order_line_size_relations ols ON ol.id = ols.order_line_id";

    List<Order> orders = null;
    using (var connection = OpenConnection(_connectionString))
    {
        orders = connection.Query<Order, OrderLine, OrderLineSize, Order>(sql, (order, orderLine, orderLizeSize) =>
        {
            orderLine.OrderLineSizes = new List<OrderLineSize> { orderLizeSize };
            order.OrderLines = new List<OrderLine>() { orderLine };
            return order;
        },
        null, commandType: CommandType.Text).ToList();
    }

    if (orders == null || orders.Count == 0)
    {
        return lookup;
    }

    foreach (var order in orders)
    {
        var contians = lookup.ContainsKey(order.id);
        if (contians)
        {
            var newLinesToAdd = new List<OrderLine>();
            var existsLines = lookup[order.id].OrderLines;
            foreach (var existsLine in existsLines)
            {
                foreach (var newLine in order.OrderLines)
                {
                    if (existsLine.id == newLine.id)
                    {
                        existsLine.OrderLineSizes.AddRange(newLine.OrderLineSizes);
                    }
                    else
                    {
                        newLinesToAdd.Add(newLine);
                    }
                }
            }
            existsLines.AddRange(newLinesToAdd);
        }
        else
        {
            lookup.Add(order.id, order);
        }
    }

    return lookup;
}


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é