简体   繁体   English

引起循环引用的对象序列化

[英]serialization of object causing circular reference

I have a simple Article class like this: 我有一个像这样的简单文章类:

   public class Article
   {
    [Key]
    public int ArticleId { get; set; }
    public string Title { get; set; }
    public string PageContent { get; set; }
    public System.DateTime PostedDate { get; set; }
    public int? ArticlePostedBy { get; set; }

    public virtual ApplicationUser ApplicationUser { get; set; }
  }

and this is my ApplicationUser class which have one to many relationship with article class : 这是我的ApplicationUser类,它与文章类有一对多的关系:

 public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
  {
    public ApplicationUser()
    {
        this.Articles = new HashSet<Article>();
    }
    public virtual ICollection<Article> Articles { get; set; }

I have configured the one to many relationship using fluent api like this: 我使用流畅的api配置了一对多的关系,如下所示:

    modelBuilder.Entity<Article>()
                   .HasOptional<ApplicationUser>(a => a.ApplicationUser)
                   .WithMany(a => a.Articles)
                   .HasForeignKey(s => s.ArticlePostedBy);

Now, this is my controller for posting the article: 现在,这是我发布文章的控制器:

    [HttpPost]
    public JsonResult Index(Article article)
    {
        article.ArticlePostedBy = User.Identity.GetUserId<int>();
        article.PostedDate = DateTime.UtcNow;
        db.Articles.Add(article);
        db.SaveChanges();
        var usr = db.Users.FirstOrDefault(x => x.Id == article.ArticlePostedBy);
        var ret = new
        {
            Title = article.Title,
            PostedBy = article.ArticlePostedBy,
            PostedByName = usr.UserName,
            PostedByAvatar = db.Users.Include(s => s.Files).SingleOrDefault(s => s.Id == article.ArticlePostedBy),
            PostedDate = article.PostedDate,
            ArticleId = article.ArticleId
        };
        return Json(ret, JsonRequestBehavior.AllowGet);
    }

Now, the problem arises when i try to post the data. 现在,当我尝试发布数据时出现问题。 On Submit button click, data got saved in the dbase but gives this server error--- A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.ApplicationUser_04102CD9A296DF3EA26BCA4B5FDF758BC1CD8B55C5601C2EA864BBE5FE4B7F46'. 单击“提交”按钮,数据已保存在dbase中,但会出现此服务器错误---序列化“System.Data.Entity.DynamicProxies.ApplicationUser_04102CD9A296DF3EA26BCA4B5FDF758BC1CD8B55C5601C2EA864BBE5FE4B7F46”类型的对象时检测到循环引用。 Now, i have read many articles on stack overflow but did not get any simple solution. 现在,我已经阅读了很多关于堆栈溢出的文章,但没有得到任何简单的解决方案。 The solution was given to disable lazy loading but I can't disable lazy loading as it is my primary need. 解决方案是禁用延迟加载,但我无法禁用延迟加载,因为这是我的主要需求。 many functions in my application would get affected due to that. 我的应用程序中的许多功能都会因此而受到影响。 Somewhere it was suggested to use ScriptIgnore. 有人建议使用ScriptIgnore。 Should I use that? 我应该用吗? If yes, where to apply that or there is any other better approach. 如果是的话,在哪里申请,或者还有其他更好的方法。 I want to apply changes only for this particular class. 我想仅对此特定类应用更改。

Your error is occurring because the anonymous object your returnind ( ret ) includes property PostedByAvatar which is typeof ApplicationUser . 您的错误正在发生,因为您的returnind( ret )的匿名对象包含属于ApplicationUser属性PostedByAvatar

ApplicationUser contains a collection of Article and Article contains a property for ApplicationUser which in turn contains a collection of Article which contains ApplicationUser and so on and so on. ApplicationUser包含ArticleArticle的集合,其中包含ApplicationUser的属性,而ApplicationUser又包含Article的集合,其中包含ApplicationUser等等。 Serializing it generates a circular reference exception. 序列化它会生成循环引用异常。

Instead of returning ApplicationUser , just return a property (or properties) of ApplicationUser that you need in the view. 而不是返回ApplicationUser ,只需返回视图中所需的ApplicationUser属性(或属性)。

var user = db.Users.Include(s => s.Files).SingleOrDefault(s => s.Id == article.ArticlePostedBy);

var ret = new
{
    Title = article.Title,
    ....
    PostedByAvatar = user.Files.someProperty;
    ....
}

Side note. 边注。 It appears you have already the user defined by var usr = db.Users.FirstOrDefault(x => x.Id == article.ArticlePostedBy); 看来你已经用var usr = db.Users.FirstOrDefault(x => x.Id == article.ArticlePostedBy);定义了用户var usr = db.Users.FirstOrDefault(x => x.Id == article.ArticlePostedBy); so it's unnecessary to call the database again (the only difference appears to be the .Include() clause so that should just be included in the var usr = .. statement). 因此不必再次调用数据库(唯一的区别似乎是.Include()子句,因此应该只包含在var usr = ..语句中)。

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

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