Verwendung von Persistence Ignorance (POCO) Adapter for Entity Framework V1 POCOs als Data contracts in WCF Service Schnittstellen

In meinem Blogeintrag https://blogs.msdn.com/mtcmuc/archive/2008/10/24/architekturaufbau-einer-multilayer-anwendung-die-mit-dem-persistence-ignorance-poco-adapter-for-entity-framework-v1-efpocoadapter-geschrieben-wurde.aspx habe ich über den Aufbau einer WCF Servicebasierten Architektur gesprochen, deren Businessentities oder Data Transfer Objekte POCOs sind. Diese POCOs haben wir mit dem Kommandozeilen Tool "EFPocoClassGen.exe" generiert und ganz normal mit einem EfPoco Adapter gefüllt. Diese POCO Objekte lassen sich auch in WCF Serviceschnittstellen verwenden.

Wenn man mit dem generierten Adapter ein solches POCO Objekt füllt und versucht das Objekt als DataContract in einem WCF Service zu verwenden, bekommt man beim Ausführen der Servicemethode eine Fehlermeldung die ungefähr so aussieht ...

 

  System.Runtime.Serialization.InvalidDataContractException: Type 'NorthwindPoco.PocoProxies.CustomersProxy' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  See the Microsoft .NET Framework documentation for other supported types. 
    at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) 
    at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode) 
    at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) 
    at WriteArrayOfCustomersToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract ) 
    at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) 
    at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph) 
    at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph) 
    at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph) 
    at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph) 
    at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph) 
    at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph) 
    at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, Object[] parameters) 
    at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest) 
    at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest) 
    at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer) 
    at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer) 
    at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer) 

Es handelt sich um eine System.Runtime.Serialization.InvalidDataContractException, die beim Serialisieren des POCOs Objektes erzeugt wird.

Der Grund für diesen Serialiiserungsfehler liegt in dem POCO, das vom Persistence Ignorance Adapter generierten Code gefüllt wurde.

Das Adapter füllt im Defaultmodus die POCO-Objekte mit sogenannten Proxies. Hierzu gibt es mehr in der Dokumentation der Persistence Ignorance Adapters.

Um die POCOs auch in einer WCF Serviceschnittstelle nutzen zu können, muss man folgenden Code verwenden ...

                 NorthwindPocoEfContext dbCtx = new NorthwindPocoEfContext();
                dbCtx.EnableChangeTrackingUsingProxies = false;              
                c = (from cust in dbCtx.Customers
                     where cust.CompanyName.StartsWith(searchString)
                     select cust).ToList<BE.Customers>();  

Mit dem Setzen des Properties "dbCtx.EnableChangeTrackingUsingProxies = false;" wird die Benutzung von Proxies verhindert.

 

Viel Spass beim Ausprobieren ... GunnarD