Подтвердить что ты не робот

Проблема множественного картографирования Dapper

Продолжайте работать. "При использовании API-интерфейсов множественного отображения убедитесь, что вы задали параметр splitOn, если у вас есть ключи, отличные от Id" для ниже кода-блока:

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 как обходной путь.

Эм я что-то пропустил?

Спасибо

Edit:

Я немного почистил свой тест, ниже - легкая версия классов и новый запрос:

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();
4b9b3361

Ответ 1

После нескольких часов отладки исходного кода Dapper я, наконец, нашел проблему, и это довольно интересно.

Когда задано несколько полей splitOn, Dapper выполняет разделение на основе запятой, например. var splits = splitOn.Split(','). ToArray(). Затем он перебирает все поля записей и разбивает их на объекты на основе указанного массива; довольно прорыв вперед.

Теперь самое интересное: когда я поставил поля splitOn, после запятой у меня было дополнительное SPACE, например. "AccountId, BranchId", и это небольшое место было причиной. После Split() поле BranchId содержало дополнительное пространство и не соответствовало ЛЮБЫМ полям в наборе записей.

Существует два способа:

  • Не используйте дополнительные пробелы после запятых; который я лично пристрастился   к; старая привычка от SQL.
  • Изменить Dappers GenerateDeserializers   метод и изменение: var currentSplit = split [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++;
            }

Update:

Вышеупомянутое исправление получилось объединенным: https://github.com/SamSaffron/dapper-dot-net/commit/399db17e5aa6f1eefaf8fdccff827020be8e6cbb