c# - EF Code First-从多到多表返回记录
问题描述
我正在尝试使用实体框架和 linq 以平面方式获取 m: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
.
查询数据时始终使用Select,并仅选择您实际计划使用的属性。仅当您计划更新获取的包含数据时才使用Include 。
这样做的原因在一对多关系中特别有意义。如果您获取“Schools with their Students”,并且 ID 为 4 的学校有 1000 个学生,那么您知道这所学校的每个学生都会有一个值为 4 的外键。将这个值 4 传递 1000 次是多么浪费!
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);
推荐阅读
- permissions - 内核如何知道应该在页表条目中设置 RWX 位的值?
- oracle - 在 Oracle PL/SQL 中解码
- python - 使用列的最大值重新组合熊猫数据框的 Pythonic 方法
- c# - Datatable.addrow 引发 System.Data.EvaluateException
- python - 从多个数据帧中获取最大长度数据帧
- python - 加密文件时如何在没有字符串参数的情况下修复编码?
- sonarqube - 我们可以在 SonarQube 中扫描 IronPython 代码吗?
- sublimetext4 - Sublime Text 3 vs Sublime Text 4:缺少“连接到服务器功能”
- postgresql-13 - PostgreSQL 读取错误:读取:没有这样的文件或目录 sql
- google-chrome-extension - 挂钩到松弛通知