我试图让在M的所有记录:在平坦的方式与实体框架和LINQ M表中。
数据模型:
public partial class Group
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid GroupId { get; set; }
[StringLength(100)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public partial class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid UserId { get; set; } = new Guid();
[StringLength(100)]
public string FirstName { get; set; }
[StringLength(100)]
public string LastName { get; set; }
[StringLength(255)]
public string DisplayName { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
下面是SQL其中拉回到我在寻找数据集中的查询:
select g.GroupId, g.[Name], u.DisplayName, u.UserId
from [Group] g, [User] u, [GroupUsers] gu
where g.GroupId = gu.Group_GroupId
and gu.User_UserId = u.UserId
order by g.[Name]
这里就是我想在LINQ的,但我发现了一个自我循环引用错误:
using (RequestContext ctx = new RequestContext())
{
return ctx.Groups.SelectMany(x => x.Users).Include(x => x.Groups).ToList();
}
这似乎是它应该是比较容易的,但我发现M:M关系在实体框架可以是一个有点棘手。任何帮助,将不胜感激。
我很高兴你定义了许多一对多的两个虚拟集合,而不指定联接表!
你一定要明白,如果你不取“组,他们的用户”,而是查询左外连接的组和用户(你把那个叫平时装),组属性将被重复了一遍又一遍,每的用户?
但是,嘿,这是你的决定,这是由你来说服你的项目负责人,这是更好百倍传递同一组属性,而不是把它们转移只有一次的。
你说的没错,一个左外连接,你需要做一个SelectMany
。我不知道为什么你决定改用Include
的Select
。
当查询数据始终使用选择,选择只有你实际计划使用的性能。如果你打算更新获取的数据包括仅使用include。
这样做的原因是一个一对多的关系,特别有意义。如果您取“与学生的学校”,并与学校ID 4有1000名学生,那么你知道这所学校的每个学生都将有一个价值4的外键多么大的浪费超过1000次传递这个值4 !
一个Enumerable.SelectMany的重载的具有参数resultSelector
,这将需要一个Group
和一个User
作为输入以生成结果。这个版本是最适合你的需要
var result = dbContext.Groups.SelectMany(
group => group.Users,
(group, user) => new
{
// Select the Group properties you plan to use
GroupId = group.GroupId,
GroupName = group.Name,
...
// Select the User properties you plan to use
UserId = user.UserId,
UserName = user.DisplayName,
...
})
// if desired do some ordering
.OrderBy(joinedItem => joinedItem.GroupName);