2012-06-14 16 views
11

seguir funcionando en "Al utilizar las API multi-mapeo asegurar que establecer el parámetro splitOn si tiene teclas que no sean Id" error para el siguiente código de bloque:Dapper Edición Multi-mapeo

var accounts = 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(); 

I' m usando SplitAccount y SplitBranch para splitOn como solución temporal.

Em I missing algo?

Gracias

Editar:

he limpiado mi prueba un poco, a continuación es una versión ligera de clases y una nueva consulta:

public class AccountLight 
{ 
    public int AccountId { get; set; } 
    public string AccountNumber { get; set; } 
    public BranchLight Branch { get; set; } 
    public ApplicationLight Application { get; set; } 
} 

public class BranchLight 
{ 
    public int BranchId { get; set; } 
    public string BranchNumber { get; set; } 
} 

public class ApplicationLight 
{ 
    public int ApplicationId { get; set; } 
    public string ApplicationCode { get; set; } 
} 

var accounts2 = DbConnection.Query<AccountLight, BranchLight, ApplicationLight, AccountLight>(
    "select Accounts.AccountId, Accounts.AccountNumber," + 
    "  Branches.BranchId, Branches.BranchNumber," + 
    "  Applications.ApplicationId, Applications.ApplicationCode" + 
    " from Accounts" + 
    " inner join Branches" + 
    "  on Accounts.BranchId = Branches.BranchId" + 
    " inner join Applications" + 
    "  on Accounts.ApplicationId = Applications.ApplicationId" + 
    " where Accounts.AccountId <> 0", 
    (account, brach, application) => 
    { 
     account.Branch = brach; 
     account.Application = application; 
     return account; 
    }, 
    commandType: CommandType.Text, 
    splitOn: "AccountId, BranchId" 
    ).AsQueryable(); 
+0

su solución está bien ... ¿qué claves primaria tiene usted sobre las tablas ? –

+0

Sam, gracias por la respuesta. A continuación están las claves: Cuenta: AccountId como PK, BranchId y ApplicationId como FK Sucursal: BranchId como PK Aplicación: ApplicationId como PK –

+0

Otra nota: Funciona si elimino la aplicación. –

Respuesta

20

Después de unas horas de depuración El código fuente de Dapper, finalmente encontré el problema y es bastante interesante.

Cuando se proporcionan varios campos splitOn, Dapper realiza una división basada en coma, p. var splits = splitOn.Split (','). ToArray(). A continuación, recorre todos los campos del conjunto de registros y los divide en objetos en función de la matriz anterior; bastante estrecho hacia adelante.

Ahora la parte divertida: cuando proporcioné mis campos splitOn, tuve un ESPACIO extra después de la coma, p. "AccountId, BranchId" y ese pequeño espacio fue la causa. Después de Split(), el campo BranchId contenía un espacio adicional y no coincidía con CUALQUIER campo en el conjunto de registros.

Hay dos maneras de evitar esto:

  1. No utilice espacios adicionales después de las comas; que personalmente adicto a; un viejo hábito de SQL.
  2. Modificar el GenerateDeserializers de Dapper método y cambio: var currentSplit = splits [splitIndex] a var currentSplit = splits [splitIndex] .Trim(), o algo similar; eso es lo que hice para mi copia local.

Aquí es el código de instantáneas:

private static Func<IDataReader, object>[] GenerateDeserializers(Type[] types, string splitOn, IDataReader reader) 
    { 
     int current = 0; 
     var splits = splitOn.Split(',').ToArray(); 
     var splitIndex = 0; 

     Func<Type, int> nextSplit = type => 
     { 
      var currentSplit = splits[splitIndex].Trim(); 
      if (splits.Length > splitIndex + 1) 
      { 
       splitIndex++; 
      } 

Actualización:

La revisión anterior consiguió fusionó: https://github.com/SamSaffron/dapper-dot-net/commit/399db17e5aa6f1eefaf8fdccff827020be8e6cbb

+4

+1, gracias por señalar: 1. no use espacios extra .... – Roger