2012-06-14 10 views
11

am Laufen halten in "Wenn die Multi-Mapping-APIs, dass Sie den splitOn param einstellen, wenn Sie andere Tasten als Id haben" Fehler für den folgenden Code-Block:Dapper Multi-Mapping-Ausgabe

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 Verwenden von SplitAccount und SplitBranch für splitOn als Workaround.

Em Ich vermisse etwas?

Dank

Edit:

ich meinen Test auf ein wenig gereinigt haben, ist eine Light-Version von Klassen und eine neue Abfrage:

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

Ihre Abhilfe ist in Ordnung ... was für Primärschlüssel haben Sie auf den Tischen haben ? –

+0

Sam, danke für die Antwort. Im Folgenden sind die Schlüssel: Konto: AccountId als PK, BranchId und ApplicationId als FK Branch: BranchId als PK Anwendung: ApplicationId als PK –

+0

Ein weiterer Hinweis: Es funktioniert, wenn ich die Anwendung entfernen. –

Antwort

20

Nach einigen Stunden der Fehlersuche Dappers Quellcode habe ich das Problem endlich gefunden und es ist ziemlich interessant.

Wenn mehrere splitOn-Felder geliefert werden, führt Dapper eine Aufteilung basierend auf Komma, z. var splits = splitOn.Split (','). ToArray(). Dann durchläuft es alle Record-Set-Felder und teilt sie in Objekte basierend auf dem obigen Array auf; ziemlich nach vorn.

Jetzt der Spaß Teil: Als ich meine SplitOn Felder lieferte, hatte ich einen zusätzlichen Platz nach dem Komma, z. "AccountId, BranchId" und dieser kleine Platz waren die Ursache. Nach dem Split() - Feld enthielt BranchId ein zusätzliches Leerzeichen und konnte nicht mit ANY-Feldern im Datensatz übereinstimmen.

Es gibt zwei Möglichkeiten, um dieses:

  1. nicht zusätzliche Leerzeichen nach Kommata Verwenden Sie; was ich persönlich süchtig zu; eine alte Gewohnheit von SQL.
  2. Ändern Dapper's GenerateDeserializers Methode und ändern: var currentSplit = teilt [splitIndex] zu var currentSplit = teilt [splitIndex] .Trim(), oder etwas Ähnliches; das habe ich für meine lokale Kopie getan.

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

Update:

Die obige fix verschmolzen wurde: https://github.com/SamSaffron/dapper-dot-net/commit/399db17e5aa6f1eefaf8fdccff827020be8e6cbb

+4

+1, danke für Hinweis: 1. Verwenden Sie keine zusätzlichen Leerzeichen .... – Roger