Как отображать объекты при использовании Dapper SplitOn? - PullRequest
2 голосов
/ 07 апреля 2019

У меня есть сохраненный процесс, который возвращает несколько строк, которые следующие столбцы:

Guid,
Guid,
Name,
Guid,
Description

Первый Guid столбец всегда одинаков для всех строк. Поэтому я создал следующие классы:

public class Header
{
    public Guid Guid { get; set; }
    public string Name { get; set; }
}

public class Content
{
    public Guid Guid { get; set; }
    public string Description { get; set; }
}

public class Result 
{
    public Guid Guid { get; set; }
    public IEnumerable<Header> Headers { get; set; }
    public IEnumerable<Content> Content { get; set; }
}

И чтобы получить результаты, которые я пытаюсь сделать:

var result connection.Query<Guid, Header, Content>("myproc", 
    new { criteria }, 
    commandType: CommandType.StoredProcedure,
    map: ,
    splitOn: "Guid").AsList();

Но что мне делать в параметре map, чтобы разделить результаты на объекты?

1 Ответ

1 голос
/ 07 апреля 2019

Я не думаю, что вы можете вызвать 3 из 5 столбцов, возвращенных с одинаковым именем (Guid), и ожидать, что Dapper выяснит, как правильно разделить.

Предполагая, что имена столбцов возвращаются изSPROC уникальны (я назвал Guid1, Guid2 и Guid3), мы разделены на Guid2 (заголовок) и Guid2 (контент).

Поскольку запрос будет возвращать по одной строке на строку, возвращаемую из Proc, нам нужно объединить и сгруппировать по родительскому идентификатору.

Я использовал здесь словарь для этого накопительного пакета:

var sql = "EXEC p_myProc";
var resultDictionary = new Dictionary<Guid, Result>();
var results = connection.Query<Result, Header, Content, Result>(
        sql,
        (result, header, content) =>
        {
            if (!resultDictionary.TryGetValue(result.Guid1, out var existingResult))
            {
                result.Headers = new List<Header>();
                result.Content = new List<Content>();
                resultDictionary.Add(result.Guid1, result);
                existingResult = result;
            }
            // Noting OP has defined the Child tables as immutable IEnumerable<>
            (existingResult.Headers as List<Header>).Add(header);
            (existingResult.Content as List<Content>).Add(content);
            return existingResult;
        },
        splitOn: "Guid2,Guid3")
    .Distinct() // Strip duplicates by reference equality
    .ToList();

Обратите внимание, что в результатах, возвращаемых Query, будет столько строк, сколько возвращает proc, но потому что мы будем возвращать одну и ту же ссылку Result для каждого Guid1 key, Distinct() удалит дубликаты.

Альтернативой этому подходу было бы сопоставить сглаженный результат сохраненного процесса во временном DOC POCO 1: 1 со всеми 5 столбцами, а затем использоватьLINQ в памяти для GroupBy Guid1 для проецирования Header и Content children.

...