Проблема множественного картографирования 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();
Ответы
Ответ 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