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

本文关键字:一对多 关系 填充 Linq Dapper 使用 | 更新日期: 2023-09-27 18:15:08

Entity - AllSalesTerritory包含代表一对多关系的List<MySalesPerson>。我有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();

BusinessEntityId是执行Sql语句

时销售实体的开始列

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

  1. 可以Dapper自动帮助我实现它,尝试了几个扩展,但他们没有像预期的那样工作
  2. Linq代码可以为我做,因为这在某种程度上与具有一对多关系的实体上的SelectMany相反

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

您可以使用字典来跟踪唯一的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();

基本上这里发生的事情是,Dapper将返回一个AllSalesTerritory和一个MySalesPerson在你的查询结果的每一行。然后,我们使用字典来查看当前AllSalesTerritory (pd)是否已经基于TerritoryId见过。如果是这样,则将本地territory变量的引用赋给该对象。如果没有,则将pd赋值给territory,然后将其添加到字典中。然后我们只需将当前的MySalesPerson (pp)添加到territory.SalesPersons列表中。