我在.net核心中使用实体框架,请注意,我对实体框架的了解有限,因此请假以为然。
团队和用户是我遇到的两个问题。
他们有一个联接表UserTeam
,因为Users
可以有许多Teams
,而Teams
可以有许多Users
。
我想出了如何使用entityframework将它们保存在sqlite数据库中的方法,这一切都很好。我花了一段时间才意识到我必须使用Include
来获得join属性,但是现在它在那部分起作用了。
在某个时候,我必须在API上公开该对象,因此我具有匹配的UserDTO
和TeamDTO
。这是我的问题。 UserDTO
有一个TeamDTO
的列表,而TeamDTO
有一个UserDTO
的列表,因为这是它们的外观。对吧?
但是当我映射它们时,我进入了StackOverflowException
,这很正常,因为我要遍历包含Users
的团队列表,并为每个{{ 1}},我最终重新创建了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
,因此我必须获取{{1 }}从上下文中使用其ID,然后我便有了所需的一切。这很奇怪,因为一切似乎都正常运行,并且数据库完整且健康。它只是缺少null
属性的Team
对象。
但是我的假设是,从ID提取新的UserTeam
到从Team
获取Team
之间,两者都会产生我现在调用{ {1}:我仍然需要遍历它的用户,并具有该溢出异常。
这似乎是一个非常普遍的问题,应该由很多人处理,但是我真的无法使用标题的关键字找到答案。
下一步是什么?
答案 0 :(得分:0)
由于您正在循环调用这2个方法,因此出现了stackoverflow。
在ToDTO
方法的团队版本中,您调用用户版本,而用户版本又在该版本中调用团队版本,依此类推。
如果您的模型未按如下所示进行结构化,则应考虑使用它。无需实际建模UserTeam
,因为EF映射应注意这一点。考虑到您已将关系的一端指定为主键。
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;}
}
答案 1 :(得分:0)
仅在需要获取对象列表时关闭延迟加载并使用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://docs.microsoft.com/en-us/ef/ef6/querying/related-data