我已经阅读了很多以前针对这个问题的解决方案,但没有一个适合我。
我在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;
以避免自引用循环。
解决此类问题的正确方法是什么?
提前致谢, 丽然!
答案 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
设置以忽略对所有/数组/对象的引用处理。
这实际上取决于您的要求和其余代码。希望其中一个能引导你走上正确的道路并祝你好运!