精巧的多映射问题

Voi*_*Ray 12 dapper

继续运行"如果使用多映射API,请确保在下面的代码块中设置了除了Id之外的其他键的splitOn参数"错误:

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();
Run Code Online (Sandbox Code Playgroud)

我正在使用SplitAccount和SplitBranch for splitOn作为解决方法.

我错过了什么?

谢谢

编辑:

我已经清理了一下我的测试,下面是一个轻量级的类和一个新的查询:

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();
Run Code Online (Sandbox Code Playgroud)

Voi*_*Ray 22

经过几个小时的Dapper源代码调试后,我终于找到了问题并且非常有趣.

当提供多个splitOn字段时,Dapper会根据逗号进行拆分,例如var splits = splitOn.Split(',').ToArray().然后它循环遍历所有记录集字段,并根据上面的数组将它们拆分为对象; 漂亮的海峡前进.

现在有趣的部分:当我提供我的splitOn字段时,我在逗号之后有一个额外的空格,例如"AccountId,BranchId",这个小空间就是原因.在Split()之后,BranchId字段包含一个额外的空格,并且无法与记录集中的任何字段匹配.

有两种方法:

  1. 逗号后不要使用额外的空格; 我个人沉迷于此; SQL的旧习惯.
  2. 修改Dapper的GenerateDeserializers方法并更改:var currentSplit = splits [splitIndex] to var currentSplit = splits [splitIndex] .Trim(),或类似的东西; 这就是我为我的本地副本所做的.

这是代码快照:

    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++;
            }
Run Code Online (Sandbox Code Playgroud)

更新:

以上修复程序已合并:https://github.com/SamSaffron/dapper-dot-net/commit/399db17e5aa6f1eefaf8fdccff827020be8e6cbb