实体框架中具有多对多关系对象的Stackoverflow异常

时间:2019-04-12 08:00:23

标签: c# entity-framework many-to-many stack-overflow

我在.net核心中使用实体框架,请注意,我对实体框架的了解有限,因此请假以为然。

团队和用户是我遇到的两个问题。

他们有一个联接表UserTeam,因为Users可以有许多Teams,而Teams可以有许多Users

我想出了如何使用entityframework将它们保存在sqlite数据库中的方法,这一切都很好。我花了一段时间才意识到我必须使用Include来获得join属性,但是现在它在那部分起作用了。

在某个时候,我必须在API上公开该对象,因此我具有匹配的UserDTOTeamDTO。这是我的问题。 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}:我仍然需要遍历它的用户,并具有该溢出异常。

这似乎是一个非常普遍的问题,应该由很多人处理,但是我真的无法使用标题的关键字找到答案。

下一步是什么?

2 个答案:

答案 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