【问题标题】:How do I map multiple lists with dapper如何使用 dapper 映射多个列表
【发布时间】:2017-08-02 14:35:00
【问题描述】:

我有三个类 User、Order 和 Project,它们存储在单个表中。订单和项目都与用户具有 n:n 关系。 为了实现这一点,我有两个映射这些关系的交叉表(UserOrders、UserProjects)。

public class User
{
  public string UserID {get;set;}
  public List<string> Orders{get;set;}
  public List<string> Projects {get;set;}
}

public class Order
{
  public string OrderID {get;set}
  ...
}

public class Project
{
  public string ProjectID {get;set}
  ...
}

如您所见,User 对象包含每个相关 orderID/projectID 的列表。

现在我想用 Dapper 查询这个。我有这个解决方案,它与 one 列表配合得很好。但是,如果我尝试查询第二个列表的完整用户对象,我将得到每个结果乘以第一个列表中的结果数。 因此,如果用户有 3 个订单和 2 个项目,则订单列表会很好,并且项目列表将包含两个项目 3 次:

var lookup = new Dictionary<string, User>();
var multi = dbDapperFM.Query<User, string, string, User>("SELECT u.*, uo.OrderID, up.ProjectID "+
        "FROM User u INNER JOIN UserOrders uo ON u.UserID=uo.UserID "+
        "INNER JOIN UserProjects up ON u.UserID=up.UserID", (u, uo, up) =>
    {
      User user;
      if (!lookup.TryGetValue(m.UserID, out user))
          lookup.Add(u.UserID, user= u);

      if (user.Orders == null)
          user.Orders = new List<string>();
      user.Orders.Add(uo);

      if (user.Projects == null)
          user.Projects = new List<string>();
      user.Projects.Add(up);
      return user;
    }, splitOn: "UserID , OrderID, ProjectID ").AsQueryable();

我明白为什么会出现这个问题(2 个内部连接),但我真的不知道如何解决它。

【问题讨论】:

    标签: c# sql orm nested dapper


    【解决方案1】:

    我也很难理解 Dapper 不会自动执行此操作的事实。

    首先,我不确定“splitOn”的逗号分隔值。我以为你在那里只能有一个值。因此,例如,我的结果集中有多个名为“ID”的列。

    其次,要获得正确的 1:N 关系,您需要执行额外的手动步骤。例如,我对参与者及其电话号码进行了 2 表连接。然后我必须这样做:

    private List<Participant> CollapseResultSet(List<Participant> rawdataset)
    {
        List<Participant> ret = new List<Participant>();
        if (!rawdataset.Any())
        {
            return ret;
        }
        else
        {
            List<string> partIds = rawdataset.Select(p => p.ID).Distinct().ToList();
            foreach (string pId in partIds)
            {
                Participant tmp = rawdataset.Where(p => p.ID == pId).FirstOrDefault();
                tmp.PhoneNumbers = rawdataset.Where(p => p.ID == pId).Select(n => n.PhoneNumbers[0]).ToList();
                ret.Add(tmp);
            }
            return ret;
        }
    }
    

    希望对您有所帮助。

    【讨论】:

    • 事实上我得到了一个类似的解决方案,我查询了 1:N 关系并用 foreach 添加了它们
    猜你喜欢
    • 1970-01-01
    • 2018-03-14
    • 2011-11-22
    • 2023-03-09
    • 1970-01-01
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多