我有三个类User,Order和Project,它们存储在单个表中。订单和项目都与用户具有: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进行查询。我有这个解决方案,可以很好地处理 一个 列表。但是,如果我尝试为第二个列表查询完整的用户对象,我将得到的每个结果都乘以第一个列表中的结果数量。因此,如果用户获得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个内部联接),但是我真的不知道如何解决它。
我也很难理解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; } }
希望能有所帮助。