使用Dapper SplitOn时如何映射对象?

时间:2019-04-07 09:20:11

标签: c# dapper

我有一个存储的proc,它返回多个行,这些行包括以下列:

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 个答案:

答案 0 :(得分:1)

我认为您不能调用以相同名称(Guid返回的5列中的3列,并希望Dapper找出如何正确拆分的方法。

假设从SPROC返回的列名是唯一的(我分别命名为Guid1Guid2Guid3),我们在Guid2(标题)和Guid2(内容)。

由于查询将返回从Proc返回的每一行中的一行,因此我们需要根据父向导进行合并和分组。

我已经使用Dictionary pattern here进行了汇总:

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键{{1 }}将删除重复项。

该方法的另一种方法是将存储过程的展平结果映射到所有5列的1:1临时DTO POCO中,然后使用内存中的LINQ将Guid1分组以进行投影淘汰Distinct()Guid1个孩子。