C# 使用Dapper或via Linq填充一对多关系

C# 使用Dapper或via Linq填充一对多关系,c#,linq,one-to-many,dapper,C#,Linq,One To Many,Dapper,实体-AllSalesTerritory包含表示一对多关系的List。我使用Sql查询来获取使用列TerritoryId映射两个实体的数据。我使用以下代码使用Dapper micro ORM填充实体: List<AllSalesTerritory> allSalesTerrotories = _connection.Query<AllSalesTerritory, MySalesPerson, AllSalesTerritory> (qu

实体-
AllSalesTerritory
包含表示一对多关系的
List
。我使用
Sql
查询来获取使用列
TerritoryId
映射两个实体的数据。我使用以下代码使用
Dapper micro ORM
填充实体:

 List<AllSalesTerritory> allSalesTerrotories = _connection.Query<AllSalesTerritory, MySalesPerson, AllSalesTerritory>
                (query, (pd, pp) =>
                {
                    pd.SalesPersons.Add(pp);
                    return pd;
                }, splitOn: "BusinessEntityId")
                .ToList();
列出所有SalesTerrotories=\u connection.Query
(查询,(pd,pp)=>
{
pd.销售人员。添加(pp);
返回pd;
},splitOn:“BusinessEntityId”)
.ToList();
BusinessEntityId
是执行Sql语句时SalesPerson实体的起始列

我面临的挑战是,这种代码有助于轻松填充一对一关系,在这里,我在每个
列表中只得到一个值,而不是在集合中聚合这些值,基本上与SQL join查询的结果相同。我可以使用一个简单的
foreach
循环并聚合
MySalesPerson
的值来轻松解决这个问题。然而,我想弄清楚:

  • Dapper可以自动帮助我实现它吗?尝试了一些扩展,但它们并没有按预期工作
  • Linq代码可以为我做到这一点吗?因为这与具有一对多关系的实体上的
    SelectMany
    有些相反

  • 您可以使用字典跟踪唯一的
    AllSalesTerritory
    对象。假设
    TerritoryId
    属性是
    int
    ,这将起作用

    var territories = new Dictionary<int, AllSalesTerritory>()
    _connection.Query<AllSalesTerritory, MySalesPerson, AllSalesTerritory>
        (query, (pd, pp) =>
        {
            AllSalesTerritory territory;
            if(!territories.TryGetValue(pd.TerritoryId, out territory))
            {
                territories.Add(pd.TerritoryId, territory = pd);
            }       
    
            territory.SalesPersons.Add(pp);
            return territory;
        }, splitOn: "BusinessEntityId");
    
    List<AllSalesTerritory> allSalesTerrotories = territories.Values.ToList();
    
    var=newdictionary()
    _连接.查询
    (查询,(pd,pp)=>
    {
    所有销售区域;
    如果(!Territions.TryGetValue(pd.TerritoryId,out territory))
    {
    地区。添加(pd.TerritoryId,territory=pd);
    }       
    地区。销售人员。添加(pp);
    返回领土;
    },splitOn:“BusinessEntityId”);
    列出所有SalesTerrotories=Territies.Values.ToList();
    

    这里发生的基本情况是Dapper将为查询结果中的每一行返回一个
    AllSalesTerritory
    和一个
    MySalesPerson
    。然后,我们使用字典查看当前的
    AllSalesTerritory
    pd
    )是否基于
    TerritoryId
    。如果是,则本地
    区域
    变量被指定该对象的引用。如果没有,那么我们将
    pd
    分配给
    territory
    ,然后将其添加到字典中。然后,我们只需将当前的
    MySalesPerson
    pp
    )添加到
    territory.Salesors
    列表中。

    谢谢,它确实有效,让我看看是否可以得到Dapper直接处理问题的响应,但是有一个问题,尽管我没有使用Dictionary,但您的解决方案也将AllSalesTerritory声明为局部变量,那么它如何在映射函数中对销售人员进行内部聚合。除了第一次,我们甚至还在从字典里取。我肯定漏掉了什么,这就是这本词典的用意。它跟踪唯一的
    AllSalesTerritory
    项目。我会在答案中添加一些描述。明白了。非常感谢,我完全遗漏了TryGetValue中的“外部区域”,它负责参考任务,因此,在分配到字典的过程中,它第一次是本地的,在字典上它是使用字典获取的,事实上,这就是为什么我们可能没有使用_connection.Query的结果,这将导致与我的问题类似的结果。如果我通过Dapper获得解决方案,那么这将作为_connection.Query的结果提供。在把你的答案标记为正确答案之前,我会等待一段时间,等待一个纯粹简洁的答案。谢谢你的帮助。据我所知,没有比简洁更自然的方法了。另外,
    查询的结果
    将包含正确的对象,但会有重复的引用。可能重复了您所引用的链接中提到的Slapper.Automapper,但它没有按预期工作,导致在dapper扩展二进制中中止调用,毫无例外,我个人从未使用过Slapper.AutoMapper,但这个问题肯定是重复的。它甚至有像我一样的字典答案。此外,这也是Dapper的创建者之一提出的相关内容。感谢@juharr,Sam的解决方案为我提供了开箱即用的解决方案,只需在GroupBy完成时对空键进行一点修改,否则字典就无法处理空键