Dapper mapeo intermedio

c# dapper orm sql-server

Pregunta

Mapeo un poco más avanzado que en mi pregunta anterior :)

Mesas:

create table [Primary] (
    Id int not null,
    CustomerId int not null,
    CustomerName varchar(60) not null,
    Date datetime default getdate(),
    constraint PK_Primary primary key (Id)
)

create table Secondary(
    PrimaryId int not null,
    Id int not null,
    Date datetime default getdate(),
    constraint PK_Secondary primary key (PrimaryId, Id),
    constraint FK_Secondary_Primary foreign key (PrimaryId) references [Primary] (Id)
)

create table Tertiary(
    PrimaryId int not null,
    SecondaryId int not null,
    Id int not null,
    Date datetime default getdate(),
    constraint PK_Tertiary primary key (PrimaryId, SecondaryId, Id),
    constraint FK_Tertiary_Secondary foreign key (PrimaryId, SecondaryId) references Secondary (PrimaryId, Id)
)

Clases:

public class Primary
{
    public int Id { get; set; }
    public Customer Customer { get; set; }
    public DateTime Date { get; set; }
    public List<Secondary> Secondaries { get; set; }
}

public class Secondary
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public List<Tertiary> Tertiarys { get; set; }
}

public class Tertiary
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
}

¿Es posible usar una selección para llenarlos todos? Algo como esto:

const string sqlStatement = @"
    select 
        p.Id, p.CustomerId, p.CustomerName, p.Date,
        s.Id, s.Date,
        t.Id, t.Date
    from 
        [Primary] p left join Secondary s on (p.Id = s.PrimaryId)
        left join Tertiary t on (s.PrimaryId = t.PrimaryId and s.Id = t.SecondaryId)
    order by 
        p.Id, s.Id, t.Id
";

Y entonces:

IEnumerable<Primary> primaries = connection.Query<Primary, Customer, Secondary, Tertiary, Primary>(
    sqlStatement,
    ... here comes dragons ...
    );

Edit1 - Podría hacerlo con dos loops anidados (foreach secondaries -> foreach terciarios) y realizar una consulta para cada elemento, pero me pregunto si podría hacerse con una sola llamada a la base de datos.

Edit2 - tal vez el método QueryMultiple sería apropiado aquí, pero si lo entiendo correctamente, necesitaría múltiples instrucciones select. En mi ejemplo de la vida real, el select tiene más de 20 condiciones (en la cláusula where), donde el parámetro de búsqueda podría ser nulo, así que no me gustaría repetir todas esas declaraciones en todas las consultas ...

Respuesta aceptada

Dapper admite Multi Mapping, para documentación ver: http://code.google.com/p/dapper-dot-net/

Este es uno de los ejemplos de uno de los proyectos en los que estoy trabajando actualmente:

        var accounts2 = DbConnection.Query<Account, Branch, Application, Account>(
                    "select Accounts.*, SplitAccount = '', Branches.*, SplitBranch = '', Applications.*" +
                    " from Accounts" +
                    "    join Branches" +
                    "       on Accounts.BranchId = Branches.BranchId" +
                    "    join Applications" +
                    "       on Accounts.ApplicationId = Applications.ApplicationId" +
                    " where Accounts.AccountId <> 0",
                    (account, branch, application) =>
                    {
                        account.Branch = branch;
                        account.Application = application;
                        return account;
                    }, splitOn: "SplitAccount, SplitBranch"
                    ).AsQueryable();

El truco es usar la opción splitOn, para dividir el conjunto de registros en múltiples objetos.

También puedes consultar mi pregunta para ver la estructura de clases para el ejemplo anterior: Dapper Multi-mapping Issue


Respuesta popular

¿Qué hay de la creación de un SQLCommand, y luego un montón de objetos SQLParameter. Idealmente con un proceso almacenado pero no tiene que serlo.

Cada uno de esos parámetros de salida podría asignarse nuevamente a sus clases.

Esta otra publicación en Stack tiene algún código que podría ser relevante.



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é