簡體   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