2012-04-19 19 views
9

Un poco más avanzado, en mis previous question :)Dapper mapeo mapeo intermedia

Tablas:

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 utilizar uno de selección para llenar a 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 luego:

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

Edit1 - Yo podría hacerlo con dos bucles anidados (secundarios foreach -> foreach terciarios) y llevar a cabo una consulta para cada artículo, pero sólo me pregunto si pudiera hacerse con una sola llamada a la base de datos.

Edit2 - tal vez el método QueryMultiple sería apropiado aquí, pero si entiendo correctamente, entonces necesitaría múltiples instrucciones de selección. En mi ejemplo de 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, por lo que no me gustaría repetir todas esas declaraciones en todas las consultas ...

Respuesta

4

Dapper soporta múltiples Cartografía, para la documentación, véase: http://code.google.com/p/dapper-dot-net/

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

 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 el splitOn opción, para dividir el conjunto de registros en múltiples objetos.

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

1

Parece que en todos los ORM tendrás varias consultas. Solo puedes crear tu propia solución, tal vez basada en Dapper o Petapoco. Por ejemplo, se combinan todas las consultas SQL en el lote uno:

select * from Primary where ... 
select * from Secondary where ... 
select * from Tertiary where ... 

A continuación, puede navegar de un conjunto de registros para NEX utilizando DataReader.NextResult()

Entonces, tienen que combinar los datos en la memoria para completar la estructura de los objetos .

1

¿Qué pasa con 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 a sus clases.

This other post en Stack tiene algún código que pueda ser relevante.