![](/img/trans.png)
[英]Entity Framework Core: many-to-many relationship with the same object
[英]Stackoverflow Exception with many-to-many relationship object in entity framework
我在 .net 核心中使用实体框架,请注意,我对实体框架的了解有些有限,所以请对我的假设持保留态度。
团队和用户是我遇到麻烦的两个对象。
他们有一个连接表UserTeam
因为Users
可以有很多Teams
,而Teams
可以有很多Users
。
我想出了如何使用 entityframework 将它们保存在 sqlite 数据库中,一切都很好。 我花了一段时间才意识到我必须使用Include
来获取连接属性,但现在它在那个部分起作用了。
在某些时候,我必须在 API 上公开该对象,所以我有匹配UserDTO
和TeamDTO
。 这是我的问题。 UserDTO
有一个TeamDTO
列表,而TeamDTO
有一个UserDTO
列表,因为它们看起来应该是这样的。 正确的?
但是当我映射它们时,我进入了StackOverflowException
,这是正常的,因为我在包含Users
的团队列表上循环,对于每个Users
,我最终重新创建Teams
,依此类推。
现在,我只是在循环中添加了一个布尔检查,所以当我调用.ToDTO()
时,我可以决定从内部级别跳过用户/团队,但这对我来说似乎不是一个合适的解决方案。 是吗?
你们有什么建议?
这就是我正在做的事情:
public static TeamDTO ToDTO(this Team team, EatupContext context, bool doOnce = false)
{
var dto = new TeamDTO
{
Id = team.Id,
Name = team.Name,
};
var users = new List<UserDTO>();
foreach (var userTeam in team.UsersTeams)
{
var user = context.Users.Find(userTeam.UserId);
if (doOnce)
user.TeamsUsers = new List<UserTeam>();
users.Add(user.ToDTO(context, true));
}
dto.Users = users;
return dto;
}
public static UserDTO ToDTO(this User user, EatupContext context, bool doOnce = false)
{
var dto = new UserDTO
{
Id = user.Id,
NickName = user.NickName,
Email = user.Email,
Image = user.Image,
};
var teams = new List<TeamDTO>();
foreach (var userTeam in user.TeamsUsers)
{
var team = context.Teams.Find(userTeam.TeamId);
if (doOnce)
team.UsersTeams = new List<UserTeam>();
teams.Add(team.ToDTO(context, true));
}
dto.Teams = teams;
return dto;
}
因为我有一种强烈的感觉,我的问题可能出自那里,所以我要分享这条信息:
当我循环遍历实体对象UserTeams
(团队或用户的)时, Team
对象为null
,因此我必须使用其 ID 从上下文中获取Team
,然后我就拥有了我需要的一切。 这很奇怪,因为一切似乎都工作正常并且数据库完整且健康。 它只是缺少Team
属性的UserTeam
对象。
但我的假设是,在从 ID 获取新Team
和从UserTeam
获取Team
之间,两者都会产生与我现在调用ToDTO()
时相同的结果:我仍然需要遍历其用户并拥有溢出异常。
这似乎是一个非常普遍的问题,应该由很多人处理,但我无法使用标题的关键字真正找到答案。
我的下一步是什么?
由于您正在循环调用这 2 种方法,因此您得到了 stackoverflow。
在ToDTO
方法的团队版本中,您调用用户版本,用户版本又调用团队版本,依此类推。
如果你的模型没有像下面这样的结构,你应该考虑它。 没有必要对UserTeam
进行实际建模,因为 EFs 映射应该会处理这个问题。 考虑到您已将关系的一端指定为主要端。
public class Team
{
public Team()
{
Users = new List<User>();
}
//properties we don't care about
public virtual ICollection<User> Users {get;set;}
}
public class User
{
public User()
{
Teams = new List<User>();
}
//properties we don't care about
public virtual ICollection<Team> Teams {get;set;}
}
当您需要获取对象列表时,只需关闭延迟加载并使用 include 方法。
这是用于 DbContext 类
public class BloggingContext : DbContext
{
public BloggingContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
这是给控制器的
using (var context = new BloggingContext())
{
// Load all blogs, all related posts, and all related comments.
var blogs1 = context.Blogs
.Include(b => b.Posts.Select(p => p.Comments))
.ToList();
// Load all users, their related profiles, and related avatar.
var users1 = context.Users
.Include(u => u.Profile.Avatar)
.ToList();
// Load all blogs, all related posts, and all related comments
// using a string to specify the relationships.
var blogs2 = context.Blogs
.Include("Posts.Comments")
.ToList();
// Load all users, their related profiles, and related avatar
// using a string to specify the relationships.
var users2 = context.Users
.Include("Profile.Avatar")
.ToList();
}
来源: https ://learn.microsoft.com/en-us/ef/ef6/querying/related-data
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.