Automapper 通过分组将 table 映射到嵌套的 class

Automapper map a table to nested class with grouping

我有 2 个 table:Staff & Address
关系是1对多(假设1个员工可以有多个地址)。

  1. 员工
    员工编号 |员工姓名
    ++++++++++++++++++++++++++
    1 |莎拉
    2 |史蒂文
    3 |大卫

  2. 地址
    地址 ID |员工编号 |街道
    +++++++++++++++++++++++++++++++++++++++++++++
    1个 | 1个 | 292橡树大道
    2个 | 1个 |松园巷 560 号
    3个 | 2个 | 1195 兰德尔驱动器
    4个 | 2个 |渡轮街 728 号
    5个 | 2个 |埃德塞尔路 4043 号
    6个 | 3个 |石南木大道 4038 号

为了获取员工信息及其地址,我在 Address table (Dapper ORM) 上使用了 LEFT JOIN 查询。
然后我得到这样的数据,

地址 ID |员工编号 |员工姓名 |街道
++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++
1个 | 1个 |莎拉 | 292橡树大道
2个 | 1个 |莎拉 |松园巷 560 号
3个 | 2个 |史蒂文 | 1195 兰德尔驱动器
4个 | 2个 | 史蒂文 |渡轮街 728 号
5个 | 2个 |史蒂文 |埃德塞尔路 4043 号
6个 | 3个 |大卫 |石南木大道 4038 号\

如何使用 AutoMapper 通过 staffId 将此数据映射到下面的 DTO?

public class StaffDto
{
    public long StaffId { get; set; }
    public string StaffName { get; set; }
    public List<Address> Address { get; set; }
}
public class Address
{
    public long AddressId { get; set; }
    public string Address{ get; set; }
}

示例数据应该是这样的:

{
  "staffId": 1,
  "staffName": "Sarah",
  "address": 
      [
          {
            "addressId": 1,
            "street": "292  Oak Drive"
          },
          {
            "addressId": 2,
            "street": "560  Pine Garden Lane"
          }
      ]
}

查阅了很多方法和资料。由于使用automapper时会用到多次循环,所以用automapper是无法达到这个要求的。但是找到了另一种方法。下面是一个例子。

根据您提供的模型生成数据库。

以正常方式获得StaffsAddresses。然后,循环处理值。

 public IActionResult get()
    {
        var staff = context.Staffs.ToList();
        var address = context.Addresses.ToList();

        foreach(var staf in staff)
        {
            staf.address = address.Where(x => x.StaffId == staf.StaffId).Select(x=> {
                x.staffDto = null;
                return x;
                }).ToList();

        }
        return Ok(staff);
    }

它可以得到那个结果。

您从地址加入员工而不是其他方式有点令人困惑,因为您不需要地址列表,而是员工及其地址列表。您根本不需要 Automapper,Dapper 可以很好地为您做到这一点。这应该可以解决问题:

var sql = "SELECT StaffId, StaffName. AddressId, Street FROM Staff INNER JOIN Address ON Staff.StaffId = Address.StaffId";
var staffDictionary = new Dictionary<int, StaffDto>();
var result = connection.Query<StaffDto, Adress, StaffDto>(sql,
    (s, a) => { 
        StaffDto staff;
        if (!staffDictionary.TryGetValue(s.StaffId, out staff))
        {
            staff = s;
            staffDictionary.Add(staff);
        }
        staff.Address.Add(a);
        return staff; 
    }, splitOn: "AddressId");
// Here are your staff
return staffDictionary;

这个想法是,如果你遇到一个“新”员工,你就把它添加到字典中,否则你就用你已经拥有的那个。在所有情况下,Address 都会添加到工作人员中。 您也许可以通过您的 LEFT JOIN 以某种方式完成这项工作,但我不明白您为什么会这样做。