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

Filling one to many relationship using using Dapper or via Linq

实体 - 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 语句时 SalesPerson 实体的起始列

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

  1. Dapper可以自动帮我实现吗,尝试了几个扩展,但没有达到预期效果
  2. 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();

基本上,这里发生的事情是 Dapper 将为查询结果中的每一行 return 一个 AllSalesTerritory 和一个 MySalesPerson。然后我们使用字典根据TerritoryId查看当前的AllSalesTerritorypd)是否已经出现过。如果是这样,则局部 territory 变量被分配到该对象的引用。如果不是,那么我们将 pd 分配给 territory,然后将其添加到字典中。然后我们只是将当前的 MySalesPerson (pp) 添加到 territory.SalesPersons 列表中。