12

继续遇到以下代码块的“使用多映射 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();

我将 SplitAccount 和 SplitBranch 用于 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();
4

1 回答 1

23

在调试了 Dapper 的源代码几个小时后,我终于找到了问题所在,这是一个非常有趣的问题。

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

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

有两种方法可以解决这个问题:

  1. 不要在逗号后使用多余的空格;我个人沉迷其中;SQL 的一个旧习惯。
  2. 修改 Dapper 的 GenerateDeserializers 方法并更改: var currentSplit = splits[splitIndex] 为 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++;
            }

更新:

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

于 2012-06-20T22:58:22.240 回答