【问题标题】:Self referencing loop detected检测到自参考循环
【发布时间】:2017-03-15 12:44:12
【问题描述】:

我已经阅读了很多针对此问题的先前解决方案,但没有一个对我有用。

我在 Event 和 User 对象之间有一个循环关系:

public class Event : EntityData
{
    [Required]
    [ForeignKey("Creator")]
    public string CreatorId { get; set; }
    public User Creator { get; set; }

    [InverseProperty("ParticipantIn")]
    public virtual ICollection<User> Participants { get; set; }

    [InverseProperty("ManagerIn")]
    public virtual ICollection<User> Managers { get; set; }
}

如你所见,我在这个类中有三个对 User 的引用:事件创建者、管理者列表和参与者列表。

用户类也包含对事件的引用:

public class User: EntityData
{
    [InverseProperty("Participants")]
    public virtual ICollection<Event> ParticipantIn { get; set; }

    [InverseProperty("Managers")]
    public virtual ICollection<Event> ManagerIn { get; set; }
}

现在,问题是当我尝试序列化一个事件时,比如在我的 createEvent 函数中,它告诉我有一个自引用循环,这是因为在创建事件时,我将它添加到创建者的'ManagerIn' 集合。

该行导致 Event->Creator->ManagerIn->Event->Creator->..... LOOP

我尝试了任何方法,我也有一个带有公共虚拟用户创建器的代码版本,以使其延迟加载..

目前,在将事件返回给我正在执行的客户端之前,我的解决方案非常不优雅:

event.Creator = null;

event.Managers = null;

为了避免自引用循环。

解决这类问题的正确方法是什么?

提前致谢, 立然!

【问题讨论】:

标签: c# entity-framework azure asp.net-web-api


【解决方案1】:

我读到这是一种方法。

MyContextEntities.ContextOptions.ProxyCreationEnabled = false;

否则,我建议序列化到不同的对象并避免序列化你的 poco。

【讨论】:

    【解决方案2】:

    因为您将集合指定为virtual,所以实体框架会延迟加载相关实体,这些实体正在构建具有循环引用的对象,而 WebAPI JSON 序列化程序不能很好地使用这些对象。

    您可以为特定查询或使用以下查询禁用延迟加载

    MyEntities.Configuration.LazyLoadingEnabled = false;
    

    或者,如果您愿意,可以从属性声明中删除 virtual 关键字。使用这些选项中的任何一个,如果需要,您可以使用 Include 扩展方法急切加载相关集合,如下所示:

    MyEntities.Set<Users>()
      .Include(u => u.ManagerIn)
      .Include("ParticipantIn");
    

    (上面显示了使用 Include to Eager Load 的两个选项)

    Load 方法也可用于显式加载相关实体。 Here 是包含与加载的堆栈溢出

    我还做了类似于您指定的将相关实体集合设置为 null 的操作,以防止将其包含在序列化中。为此,我建议首先将您的 POCO / 实体映射到 DTO(数据传输对象),这样您就可以设置可重复的内容,并避免在同一上下文中意外调用 SaveChanges() 并无意中删除 SQL 中实体之间的关系。 Automapper 是一个现有的解决方案,可以将此映射到 DTO,或者您可以编写自己的 Mapper 实用程序类来给自己更多的控制权。

    最后一个可能的选项(我知道)是调整 HttpConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandinging 设置以忽略对所有内容/数组/对象的引用处理。

    这实际上取决于您的要求和代码的其余部分。希望其中之一能引导您走上正确的道路并祝您好运!

    【讨论】:

    • 嗨,伙计!感谢您指定的答案。但无论我做什么,我仍然会收到这个错误。让我举一个例子。在我的创建事件函数中,我正在执行 var inserted = context.Events.Add(event);添加事件,然后我找到使用 var creator = await context.Users.FindAsync(new object[] { creatorId }); 创建事件的用户,我这样做是为了执行 creator.ManagerIn.Add(created );所以该事件将在他的名单上。一旦我加载创建者对象,插入的对象现在包含对具有事件引用等的创建者的循环引用......
    猜你喜欢
    • 1970-01-01
    • 2021-11-18
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2014-02-01
    • 1970-01-01
    相关资源
    最近更新 更多