我有三个课程User,Order&项目存储在单个表中。订单和项目都与用户有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查询。我有这个解决方案,与一个列表相当不错。但是,如果我尝试查询第二个列表的完整用户对象,我将得到每个结果乘以第一个列表中的结果数。 因此,如果用户有3个订单和2个项目,那么订单清单就可以了,项目清单将包含两个项目:
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个内部联接),但我真的没有办法解决它。
答案 0 :(得分: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;
}
}
希望有所帮助。