utilizando Dapper MultiMapper con una consulta de combinación externa

c# dapper

Pregunta

Esta es la primera vez que uso Dapper y estoy tratando de lograr lo siguiente

Tenemos nuestros objetos de dominio definidos como

public class Company
{
    public Int64 company_id { get; set; }

    public ICollection<Brand> Brands { get; set; }

    public ICollection<CompanyConnector> CompanyConnectors { get; set; }
}

public class Brand
{
    public Int64 brand_id { get; set; }

    public Int64 company_id { get; set; }

    public string brand_name { get; set; }
}

public class CompanyConnector
{
    public Int64 company_connector_id { get; set; }

    public Int64 company_id { get; set; }
}

Estoy intentando utilizar el mapeador múltiple en Dapper para obtener una empresa, todas sus marcas (esto es opcional) y todos los conectores (también opcional).

Tengo la consulta con una combinación externa izquierda

select company.*, brand.* , company_connector.*
from company 
left outer join brand on company.company_id = brand.company_id
left outer join company_connector on company.company_id=        company_connector.company_id

El código para obtener los datos es

var lookup = new Dictionary<Int64, Company>();
connection.Query<Company, Brand, CompanyConnector, Company>(strQuery,
(c, b, cc) =>
{
    Company cm;
    if (!lookup.TryGetValue(c.company_id, out cm))
    {
        lookup.Add(c.company_id, cm = c);
    }

    if (null != b)
    {
        if (null == cm.Brands)
            cm.Brands = new List<Brand>();
        cm.Brands.Add(b);
    }

    if (null != cc)
    {
        if (null == cm.CompanyConnectors)
            cm.CompanyConnectors = new List<CompanyConnector>();
        cm.CompanyConnectors.Add(cc);
    }

    return cm;
}, splitOn: "brand_id, company_connector_id"
).AsQueryable();

Como una empresa tiene 2 marcas y 2 conectores, la combinación externa resulta en 4 filas, por lo que los objetos resultantes tienen 4 entradas de marca y 4 entradas de conector

Puedo agregar la línea de código para verificar si el objeto existe antes de agregarlo a la lista

if(!cm.Brands.Any(item => item.brand_id == b.brand_id))
cm.Brands.Add(b);

Pregunta: ¿estoy usando esto de la manera correcta? ¿Cuál es la solución para mí obtener la cantidad correcta de registros de marca y conector?

Respuesta popular

Por lo que veo, Dapper no admite directamente la carga de colecciones para niños, por lo que tiene el código para realizar la búsqueda, verificar nulos, agregar valores ...

Acabo de agregar un cheque allí para ver si el valor ya se agregó a la colección.

var lookup = new Dictionary<Int64, Company>();
connection.Query<Company, Brand, CompanyConnector, Company>(strQuery,
(c, b, cc) =>
{
    Company cm;
    if (!lookup.TryGetValue(c.company_id, out cm))
    {
        lookup.Add(c.company_id, cm = c);
    }

    if (null != b)
    {
        if (null == cm.Brands)
            cm.Brands = new List<Brand>();
        if(!cm.Brands.Any(r=>r.brand_id == b.brand_id ))
            cm.Brands.Add(b);
    }

    if (null != cc)
    {
        if (null == cm.CompanyConnectors)
            cm.CompanyConnectors = new List<CompanyConnector>();
        if(!cm.CompanyConnectors.Any(r=>r.company_connector_id  == b.company_connector_id  ))
            cm.CompanyConnectors.Add(cc);
    }

    return cm;
}, splitOn: "company_id, brand_id, company_connector_id"
).AsQueryable();

Otra cosa que se podría hacer es cargar las 3 colecciones de forma separable y asignarlas fuera de la función dapper.

select * from company
select * from brand b join company c on c.company_id = b.company_id
select * from company_connector b join company c on c.company_id = b.company_id


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é