2012-06-14 10 views
11

continuare a correre in "Quando si usano le API multi-mapping assicurarsi di impostare il parametro splitOn se si dispone di chiavi diverse da Id" errore per il sottostante codice di blocco:Dapper Multi-mappatura Problema

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 e SplitBranch per splitOn come soluzione alternativa.

Em Mi manca qualcosa?

Grazie

Edit:

ho ripulito la mia prova un po ', qui di seguito è una versione leggera di classi e di una nuova query:

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

vostra soluzione va bene ... quello che le chiavi primarie cosa avete sui tavoli ? –

+0

Sam, grazie per la risposta. Di seguito sono riportate le chiavi: Account: AccountId come PK, BranchId e ApplicationId come FK Branch: BranchId come PK Applicazione: ApplicationId come PK –

+0

Un'altra nota: Funziona se rimuovo l'applicazione. –

risposta

20

Dopo poche ore di debugging Il codice sorgente di Dapper, ho finalmente trovato il problema ed è piuttosto interessante.

Quando vengono forniti più campi SplitOn, Dapper esegue una divisione in base alla virgola, ad es. var divide = splitOn.Split (','). ToArray(). Quindi scorre in tutti i campi del record set e li divide in oggetti basati sull'array precedente; abbastanza stretto in avanti.

Ora la parte divertente: quando ho fornito i miei campi splitOn, avevo uno SPAZIO extra dopo la virgola, ad es. "AccountId, BranchId" e quel piccolo spazio era la causa. Dopo Split(), il campo BranchId conteneva uno spazio extra e non corrispondeva a QUALSIASI campo nel set di record.

Ci sono due modi per aggirare questo:

  1. Non utilizzare spazi aggiuntivi dopo la virgola; che ho personalmente addicted a; una vecchia abitudine di SQL.
  2. Modificare il metodo GenerateDeserializers di Dapper e modificare: var currentSplit = divide [splitIndex] in var currentSplit = divide [splitIndex] .Trim() o qualcosa di simile; questo è quello che ho fatto per la mia copia locale.

Ecco il codice snapshot:

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++; 
      } 

Aggiornamento:

La correzione sopra ottenuto è fusa: https://github.com/SamSaffron/dapper-dot-net/commit/399db17e5aa6f1eefaf8fdccff827020be8e6cbb

+4

+1, grazie per precisare: 1. non usare spazi extra .... – Roger