检测到自引用循环

时间:2017-03-15 12:44:12

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

我已经阅读了很多以前针对这个问题的解决方案,但没有一个适合我。

我在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的引用:事件创建者,管理者列表和参与者列表。

用户类也包含对Event的引用:

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

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

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

该行导致Event-&gt; Creator-&gt; ManagerIn-&gt; Event-&gt; Creator-&gt; ..... LOOP

我尝试过任何东西,我还有一个带有公共虚拟User Creator的代码版本,以便让它懒得加载..

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

event.Creator = null;

event.Managers = null;

以避免自引用循环。

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

提前致谢, 丽然!

2 个答案:

答案 0 :(得分:0)

我读到这是一种方法。

MyContextEntities.ContextOptions.ProxyCreationEnabled = false;

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

答案 1 :(得分:0)

因为您将集合指定为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设置以忽略对所有/数组/对象的引用处理。

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