我有一个 Reason 对象:
public class Reason
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual Company Company {get;set;}
}
我正在使用 Entity Framework 4,公司是公司的导航属性。
我还使用网络服务来将数据返回给客户端。
我有返回原因的网络方法:
[WebMethod]
public Reason[] GetCallReasons()
{
IReasonRepository rep =
ObjectFactory.GetInstance<IReasonRepository>();
return rep.GetReasonsList().ToArray();
}
由于 ef4,我在执行 web 方法时遇到以下异常:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Reason_24A0E4BBE02EE6BC2CF30BB56CFCB670C7D9D96D03D40AF4D174B89C9D3C5537'
问题出现是因为 ef4 添加了无法序列化的属性:
为了解决这个问题并消除错误,我可以通过不将其设为虚拟或删除导航属性来禁用导航属性。但我需要它并想使用延迟加载功能。
我也可以为 Reason 编写特定的序列化程序,但我在我的 Web 服务中使用了很多类,并且为所有这些类编写一个序列化程序是一项大量的工作。
我该如何解决这个异常?..
最佳答案
您的问题有多种解决方案,它们实际上取决于您使用的服务类型和序列化类型:
- 干净的方法是使用 DTO(数据传输对象),正如 @Mikael 已经建议的那样。 DTO 是一个特殊的对象,它只传输你所需要的,仅此而已。您可以简单地创建不包含循环引用的 DTO 并使用 AutoMapper在实体和 DTO 之间映射,反之亦然。为@Mikael +1,因为他是第一个提到这一点的人。
所有其他方法都基于 @Haz 建议的 tweeking 序列化:
- WCF 和
DataContractSerializer
:使用DataContract[IsReference=true]
显式标记您的实体,使用[DataMember]
属性显式标记所有属性。这将允许您使用循环引用。如果您使用 T4 模板生成实体,则必须对其进行修改以添加这些属性。 - WCF 和
DataContractSerializer
:隐式序列化。使用[IgnoreDataMember]
属性标记一个相关的导航属性,这样属性就不会被序列化。 XmlSerializer
:用[XmlIgnore]
属性标记一个相关的导航属性- 其他序列化:使用
[NonSerialized]
标记一个相关的导航属性(+1,因为他是第一个提到这个的)用于普通序列化或[ScriptIgnore]
用于一些 JSON 相关的序列化。
关于c# - ef4 导致 Web 服务中的循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5762135/