Dapper - 多映射 API 确保您设置 splitOn

Posted

技术标签:

【中文标题】Dapper - 多映射 API 确保您设置 splitOn【英文标题】:Dapper - multi-mapping APIs ensure you set the splitOn 【发布时间】:2020-08-26 20:11:16 【问题描述】:

对于下面显示的代码,我收到以下错误消息。

*** 错误 ***

使用多映射 API 时,请确保设置 splitOn 参数,如果 您有除 Id 以外的键(参数“splitOn”)

据我了解,我正在传递 splitOn 参数,我是否遗漏了一些明显的东西?

代码


 using (var connection = new Microsoft.Data.SqlClient.SqlConnection(connectionString))
                
                    connection.Open();
                    LookupTables = connection.Query<LookupTable, List<LookupValue>, LookupTable>("exec [lookups].[SelAllLookupTable]", 
                        (lookuptable, lookupvalue) => 
                            lookuptable.LookUpValues = lookupvalue.ToList<LookupValue>(); 
                            return lookuptable;
                        , splitOn: "LookupValueID").ToList();
                


更新

存储的过程代码


ALTER PROCEDURE [lookups].[SelAllLookupTable]
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT lt.[LookupTableID],
        lt.[GUID],
        lt.[CreatedBy],
        lt.[CreatedOn],
        lt.[UpdatedBy],
        lt.[UpdatedOn],
        lt.[ChangeReason],
        lt.[Name],
        lt.[Description],
        lv.[LookupValueID],
        lv.[LookupTableID],
        lv.[GUID],
        lv.[CreatedBy],
        lv.[CreatedOn],
        lv.[UpdatedBy],
        lv.[UpdatedOn],
        lv.[ChangeReason],
        lv.[Description],
        lv.[DisplayOrderNo]
    FROM lookups.LookupTable lt
    LEFT JOIN lookups.LookupValue lv ON lt.LookupTableID = lv.LookupTableID
END


【问题讨论】:

能否添加存储过程的SQL代码? @Steve 我已经添加了存储的过程代码,谢谢 我会尝试添加字段名称而不是 * 并且您只需要 splitOn 参数中连接表的 ID LookupTableID 感谢您稍微移动了代码,我现在得到了结果,虽然我期待 1 个包含 2 个查找值的列表的查找表,但我是 2 个没有值的查找表 【参考方案1】:

我没有你的数据,但我认为你应该以这种方式更改代码

// Where we store the distinct LookUpTable found by the query
Dictionary<int, LookUpTable> result = new Dictionary<int, LookUpTable>();

using (var connection = new Microsoft.Data.SqlClient.SqlConnection(connectionString))

    connection.Open();
    var LookupTables = connection.Query<LookupTable, LookUpValue, LookupTable>("exec [lookups].[SelAllLookupTable]",
        (lkt, lkv) =>
        
            // Check if we have the instance already in the dictionary
            // add it if not, 
            if (!result.ContainsKey(lkt.LookUpTableID))
               result.Add(lkt.LookUpTableID, lkt);
            result[lkt.LookupTableID].LookUpValues.Add(lkv);
            return lkt;
        , splitOn: "LookupValueID").ToList();

return result.Values.ToList();

Dapper 不会直接构建和传递 LookUpValue 列表,但它会遍历记录,从每个返回的记录创建对象并将这些对象一一传递给 lambda 表达式。 您的 lambda 表达式可以使用 Dictionary 来存储收到的每个 LookupTable 对象,并将 LookupValue 对象添加到其属性中。当 Dapper 结束对记录的迭代时,您的对象将存储在字典的 Values 集合中

当然这假设你的类 LookUpTable 有一个List&lt;LookUpValue&gt; 属性

public class LookupTable

    public int LookupValueID  get; set; 
    .... other properties ....
    public List<LookUpValue> LookUpValues get;set = new List<LookUpValue>();

注意属性如何在初始化时创建列表以避免 Dapper lambda 表达式中的复杂逻辑。

【讨论】:

代码现在正在运行并且正在返回数据但是对于结果我期望一个包含 2 个查找值的列表的查找表但是我得到了 2 个查找表,每个查找值有 1 个 我明白了,我现在更好地理解了您的情况并更改了示例。这是 dapper 的常见场景,可以借助字典变量来解决 啊,太好了,谢谢你,你是最棒的!就像我想要的那样工作:) 重新检查了这段代码,出现了错误。在字典中,应该向 LookupTable 添加一个引用,而不是向 LookupValue 添加一个引用(除非您手动编写这样的代码,否则您不会足够欣赏 Intellisense)

以上是关于Dapper - 多映射 API 确保您设置 splitOn的主要内容,如果未能解决你的问题,请参考以下文章

在dapper中使用一对多关系时出现splitOn错误

Dapper Orm 删除异常

使用多映射 API 时,如果您的键不是 Id“、”splitOn 和多个关系,请确保设置 splitOn 参数

.NET CORE:Dapper 映射多对多查询

Dapper 的 DDD 原则和存储库

如何在 Dapper 上执行严格的映射