您正在 WCF 服务中使用实体框架,并且您正在返回从数据库中检索到的实体。 EF 动态创建您的类的代理子类。 WCF 不知道如何处理代理子类。
这篇文章有更多细节:
http://msdn.microsoft.com/en-us/library/vstudio/ee705457(v=vs.100).aspx
POCO代理类型不能被直接序列化或反序列化
Windows 通信基金会 (WCF),因为
DataContractSerializer 序列化引擎只能序列化和
反序列化已知类型。代理类型不是已知类型。更多
信息,请参阅工作中的序列化 POCO 代理部分
与 POCO 实体主题。要将 POCO 代理序列化为 POCO 实体,
使用 ProxyDataContractResolver 类将代理类型映射到 POCO
序列化期间的类型。
由于某种原因,MS 提供了 ProxyDataContractResolver,但没有提供应用解析器的属性。本文描述了实现 ApplyDataContractResolverAttribute 以及如何将其应用于操作。
更新:
在处理循环引用时,直接通过 WCF 返回 EF 对象存在相关问题。假设 A 类与 B 类具有多对一关系。A 具有到 B 的导航属性,B 具有 A 的集合。这可以通过使用属性 [DataContract(IsReference=true)] 标记 DataContract 来处理,但是如果您要传回 EF 对象,您可能不想将 DataContract 和 DataMember 添加到模型中的每个类。相反,DataContractSerializer 可以通过将 preserveObjectReferences 设置为 true 来为您处理此问题。 Sowmy Srinivasan 有一篇很棒的文章描述了如何做到这一点:Preserving Object Reference in WCF
结合使用 ProxyDataContractResolver 和 preserveObjectReferences = true 的两种方法,我想出了这些类:
public class ReferencePreservingProxyDataContractSerializerOperationBehavior
: DataContractSerializerOperationBehavior
{
public ReferencePreservingProxyDataContractSerializerOperationBehavior(
OperationDescription operationDescription)
: base(operationDescription) { }
public override XmlObjectSerializer CreateSerializer(
Type type, string name, string ns, IList<Type> knownTypes)
{
return CreateDataContractSerializer(type, name, ns, knownTypes);
}
private static XmlObjectSerializer CreateDataContractSerializer(
Type type, string name, string ns, IList<Type> knownTypes)
{
return CreateDataContractSerializer(type, name, ns, knownTypes);
}
public override XmlObjectSerializer CreateSerializer(
Type type, XmlDictionaryString name, XmlDictionaryString ns,
IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
0x7FFF /*maxItemsInObjectGraph*/,
false/*ignoreExtensionDataObject*/,
true/*preserveObjectReferences*/,
null/*dataContractSurrogate*/,
new ProxyDataContractResolver());
}
}
public class ReferencePreservingProxyDataContractFormatAttribute : Attribute, IOperationBehavior
{
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
{
IOperationBehavior innerBehavior = new ReferencePreservingProxyDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyClientBehavior(description, proxy);
}
public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
IOperationBehavior innerBehavior = new ReferencePreservingProxyDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyDispatchBehavior(description, dispatch);
}
public void Validate(OperationDescription description)
{
}
}
然后对于每个操作,我只是应用 [ReferencePreservingProxyDataContractFormatAttribute]