繁体   English   中英

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

[英]Stackoverflow Exception with many-to-many relationship object in entity framework

我在 .net 核心中使用实体框架,请注意,我对实体框架的了解有些有限,所以请对我的假设持保留态度。

团队和用户是我遇到麻烦的两个对象。

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

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

在某些时候,我必须在 API 上公开该对象,所以我有匹配UserDTOTeamDTO 这是我的问题。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM