繁体   English   中英

自引用循环检测到EF / Json

[英]Self referencing loop detected EF / Json

我正在使用实体框架(代码优先),并且已经映射了所有实体并禁用了延迟加载。 这很好,但是一旦我尝试做一些Ajax工作,我就会开始遇到问题。

第一个问题与我的User类有关。 看起来像这样:

public partial class User : IdentityUser
{
    public string CompanyId { get; set; }
    public string CreatedById { get; set; }
    public string ModifiedById { get; set; }
    public System.DateTime DateCreated { get; set; }
    public Nullable<System.DateTime> DateModified { get; set; }
    public System.DateTime LastLoginDate { get; set; }
    public string Title { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string Email { get; set; }
    public string JobTitle { get; set; }
    public string Telephone { get; set; }
    public string Mobile { get; set; }
    public string Photo { get; set; }
    public string LinkedIn { get; set; }
    public string Twitter { get; set; }
    public string Facebook { get; set; }
    public string Google { get; set; }
    public string Bio { get; set; }
    public string CompanyName { get; set; }
    public string CredentialId { get; set; }
    public bool IsLockedOut { get; set; }
    public bool IsApproved { get; set; }
    public bool CanEditOwn { get; set; }
    public bool CanEdit { get; set; }
    public bool CanDownload { get; set; }
    public bool RequiresApproval { get; set; }
    public bool CanApprove { get; set; }
    public bool CanSync { get; set; }
    public bool AgreedTerms { get; set; }
    public bool Deleted { get; set; }

    public Company Company { get; set; }
    public User CreatedBy { get; set; }
    public User ModifiedBy { get; set; }
    public ICollection<Asset> Assets { get; set; }
    public ICollection<Category> Categories { get; set; }
    public ICollection<Collection> Collections { get; set; }
    public ICollection<Comment> Comments { get; set; }
    public ICollection<LocalIntegration> LocalIntegrations { get; set; }
    public ICollection<Page> Pages { get; set; }
    public ICollection<Rating> Ratings { get; set; }
    public ICollection<Theme> Themes { get; set; }
    public ICollection<Group> MemberOf { get; set; }
    public ICollection<Category> ForbiddenCategories { get; set; }
    public ICollection<Page> ForbiddenPages { get; set; }
}

现在,由于禁用了延迟加载 ,因此我改用Eager加载 ,如果我在调用此方法时对此有所了解:

    // 
    // AJAX: /Users/Get
    public JsonResult Get()
    {
        try
        {
            using (var uow = new UnitOfWork<SkipstoneContext>())
            {
                var service = new UserService(uow, User.Identity.GetUserId(), this.CompanyId);
                var u = service.GetAll("MemberOf");

                return new JsonResult { Data = new { success = true, users = u } }; // Return our users
            }
        }
        catch (Exception ex)
        {
            return new JsonResult { Data = new { success = false, error = ex.Message } };
        }
    }

我可以清楚地看到仅填充了Members导航属性。 其余部分为空。

如果我尝试将u传递给JsonResult ,那么就会出现问题。 我得到错误:

检测到类型为'System.Data.Entity.DynamicProxies.User_E9B58CAAA82234358C2DE2AF8788D33803C4440F800EA8E015BE49C58B010EDF'的属性'CreatedBy'的自引用循环。 路径“用户[0]”。

在另一篇文章中,我读到发生这种情况是因为Json.Net试图序列化并填充所有导航属性。

因此,我创建了一个新项目,并在其中创建了两个模型:

public class User
{
    public User()
    {
        this.Id = Guid.NewGuid().ToString();
    }

    public string Id { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
    public string CreatedById { get; set; }

    public ICollection<Post> Posts { get; set; }
    public User CreatedBy { get; set; }
}

public class Post
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Message { get; set; }
    public string CreatedById { get; set; }

    public User CreatedBy { get; set; }
}

我希望运行该命令会出现自引用错误,因为User不仅有很多Post ,而且还有一个User创建了它。

因此该方法如下所示:

public JsonResult Get()
{
    try
    {
        var user = new User()
        {
            UserName = "moo",
            Email = "moo@moo.co.uk"
        };

        return new JsonResult { Data = new { sucess = true, user = user } };
    }
    catch (Exception ex)
    {
        return new JsonResult { Data = new { sucess = true, error = ex.Message } };
    }
}

同样,(在我看来)这与第一个项目相同。 无论如何,当我运行它时,项目运行正常。

有人可以向我解释为什么会发生这种情况以及我该怎么做才能解决?

我假设您的导航属性实际上已标记为virtual ,否则EF不会尝试延迟加载它们...

只是将相同类型的导航属性嵌套在对象的虚拟属性中并不能使其自引用。 当属性为null,空集合时,或者当JSON序列化程序在遍历实体的所有属性后可以“找到出路”时,则它不是自引用。 自引用是指我从“用户”转到“帖子”,然后再回到同一用户,再回到其用户,依此类推,等等。

要解决此问题,请勿尝试序列化实体。 相反,请先将它们转换为视图模型,然后序列化视图模型。

public class UserViewModel
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
    public string CreatedById { get; set; }
    public ICollection<PostViewModel> Posts { get; set; }
    public string CreatedByUserName { get; set; } // end self-referencing
}

public class PostViewModel
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string Message { get; set; }
    public string CreatedById { get; set; }
    public string CreatedByUserName { get; set; } // end self-referencing
}

public JsonResult Get()
{
    try
    {
        using (var uow = new UnitOfWork<SkipstoneContext>())
        {
            var service = new UserService(uow, User.Identity.GetUserId(), this.CompanyId);
            var u = service.GetAll("MemberOf");
            var vm = Mapper.Map<UserViewModel[]>(u);
            return new JsonResult { Data = new { success = true, users = vm } }; // Return our users
        }
    }
    catch (Exception ex)
    {
        return new JsonResult { Data = new { success = false, error = ex.Message } };
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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