Procedura dettagliata: serializzare proxy POCO con WCF (Entity Framework)
Non è possibile serializzare o deserializzare direttamente il proxy POCO in WCF (Windows Communication Foundation), in quanto il motore di serializzazione DataContractSerializer consente di serializzare e deserializzare solo i tipi noti e il tipo proxy non è un tipo noto. Per ulteriori informazioni, vedere la sezione dedicata alla serializzazione dei proxy POCO nell'argomento Utilizzo di entità POCO (Entity Framework). Per serializzare i proxy POCO come entità POCO, utilizzare la classe ProxyDataContractResolver per eseguire il mapping dei tipi proxy ai tipi POCO durante la serializzazione.
Nell'esempio riportato in questo argomento viene descritto come indicare all'oggetto DataContractSerializer di utilizzare la classe ProxyDataContractResolver nelle operazioni del servizio definendo una classe Attribute, che sarà applicata alle operazioni del servizio, in cui viene utilizzato internamente l'oggetto ProxyDataContractResolver per il mapping dei tipi proxy ai tipi POCO. Viene inoltre illustrato come associare la classe Attribute ai metodi che fanno parte di un contratto di servizio nell'applicazione WCF.
Negli esempi inclusi in questo argomento vengono utilizzate le classi POCO definite in Procedura: definire entità POCO (Entity Framework) e un modello di dati basato su AdventureWorks definito in Procedura: personalizzare i file di mapping e di modellazione per l'utilizzo con oggetti personalizzati (Entity Framework).
Per creare il progetto Libreria di classi contenente classi POCO.
Creare un nuovo progetto Libreria di classi denominato POCOAdventureWorksModel.
Rimuovere il file di codice sorgente predefinito aggiunto al progetto.
Aggiungere che un modello vuoto denominato AdventureWorksModel. Per creare un modello vuoto, vedere la sezione Come creare un file con estensione edmx nell'argomento How to: Create a New .edmx File. Modificare il modello seguendo i passaggi descritti in File con estensione AdventureWorks.edmx personalizzato (Entity Framework).
Disabilitare la generazione di codice per il file con estensione edmx. Aprire il file con estensione edmx in ADO.NET Entity Data Model Designer (Entity Designer). Fare clic con il pulsante destro del mouse nell'area di progettazione e scegliere Proprietà. Nella finestra Proprietà selezionare la proprietà Strategia di generazione del codice e quindi None. Se la finestra Proprietà non viene visualizzata, premere F4.
Aggiungere il file app.config al progetto Libreria di classi. Fare clic con il pulsante destro del mouse su POCOAdventureWorksModel, scegliere Aggiungi, quindi Nuovo elemento.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare il modello Generale, quindi scegliere File di configurazione dell'applicazione. Copiare il codice seguente tra i tag configuration nel file di configurazione dell'applicazione. Modificare il valore Data Source se necessario.
<connectionStrings> <add name="AdventureWorksEntities" connectionString="metadata=res://*/AdventureWorksModel.csdl|res://*/AdventureWorksModel.ssdl|res://*/AdventureWorksModel.msl; provider=System.Data.SqlClient;provider connection string=" Data Source=(local);Initial Catalog=AdventureWorks; Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" /> </connectionStrings>
Aggiungere un riferimento alla libreria System.Runtime.Serialization. Questa libreria è necessaria per gli attributi DataContract e DataMember di WCF utilizzati sui tipi di entità serializzabili.
Aggiungere una nuova classe denominata
POCOClasses
al progetto. Aggiungere il codice in Classi POCO serializzabili basate sul modello di AdventureWorks al file. Contiene le definizioni del tipo di entità e del contesto dell'oggetto.Compilare il progetto.
Per creare e configurare il progetto WCF.
Creare un progetto WCF Service Application nella stessa soluzione del progetto Libreria di classi denominato POCOAdventureWorksService.
Aggiungere un riferimento alla libreria System.Data.Entity.
Aggiungere un riferimento al progetto POCOAdventureWorksModel, ovvero il progetto in cui è definito il modello.
Aggiungere la stringa di connessione al file con estensione config in modo che mediante il runtime di Entity Framework sia possibile trovare i metadati. Aprire il file app.config nel progetto POCOAdventureWorksModel, copiare l'elemento connectionStrings e aggiungerlo come elemento figlio dell'elemento configuration al file Web.config.
Creare una nuova classe e denominarla
ApplyDataContractResolverAttribute
.Aggiungere i seguenti spazi dei nomi all'inizio del file:
using System.Data.Objects; using System.ServiceModel.Description; using System.ServiceModel.Channels;
Sostituire il codice generato per la nuova classe con il codice seguente:
public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior { public ApplyDataContractResolverAttribute() { } public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { } public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy) { DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>(); dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver(); } public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch) { DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>(); dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver(); } public void Validate(OperationDescription description) { // Do validation. } }
Aprire il file di interfaccia di servizio. Per impostazione predefinita, si tratta di IService1.
Aggiungere lo spazio dei nomi
POCOAdventureWorksModel
all'inizio del file. Si tratta dello spazio dei nomi in cui sono definiti i tipi POCO.Sostituire il codice che definisce il file dell'interfaccia di servizio con il codice riportato di seguito:
[ServiceContract] public interface IService1 { [OperationContract] [ApplyDataContractResolver] void UpdateOrder(Order updated); [OperationContract] [ApplyDataContractResolver] Order GetOrder(int OrderID); }
Aprire il codice sorgente del servizio. Per impostazione predefinita, si tratta di Service1.srv.cs (o con estensione vb).
Aggiungere lo spazio dei nomi
POCOAdventureWorksModel
all'inizio del file.Sostituire il codice che definisce la classe del servizio con il codice riportato di seguito:
public class Service1 : IService1 { public void UpdateOrder(Order updated) { using (POCOAdventureWorksEntities context = new POCOAdventureWorksEntities()) { // Attach the original order to the context by querying the database. // Alternatively, you can require that the updated object be returned along with the original object from the client. // This means the client would need to clone the original object. Order original = context.Orders.SingleOrDefault(o => o.SalesOrderID == updated.SalesOrderID); // Apply changes to the order object. context.Orders.ApplyCurrentValues(updated); context.SaveChanges(); } } public Order GetOrder(int OrderID) { using (POCOAdventureWorksEntities context = new POCOAdventureWorksEntities()) { // You can disable the proxy creation // by setting context.ContextOptions.ProxyCreationEnabled to false context.ContextOptions.LazyLoadingEnabled = false; // The order was created as a POCO proxy object. // But it will be recieved on the client as a pure POCO. Order order = context.Orders.SingleOrDefault(o => o.SalesOrderID == OrderID); return order; } } }
Compilare il progetto.
Per eseguire il test del servizio.
Creare un'applicazione console. Digitare POCOAdventureWorksTest per il nome del progetto.
Aggiungere un riferimento al progetto POCOAdventureWorksModel.
Aggiungere un riferimento al servizio POCOAdventureWorksService. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella di riferimento e scegliere Aggiungi riferimento al servizio.
Aprire il file app.config e aggiungere la stringa di connessione al file. Aprire il file app.config per POCOAdventureWorksModel, copiare l'elemento connectionStrings e aggiungerlo come elemento figlio dell'elemento configuration del file Web.config.
Aprire il file che contiene la funzione principale.
Aggiungere gli spazi dei nomi seguenti, dove sono definiti il servizio e i tipi POCO, all'inizio del file:
Service1Client client = new Service1Client(); int orderId = 43680; Order order = client.GetOrder(orderId); Console.WriteLine(order.DueDate); // Modify order. order.DueDate = DateTime.Now; // Update order in the database. client.UpdateOrder(order);
Sostituire il codice con il seguente. Si noti che anche se il servizio è in grado di serializzare proxy POCO, il client riceve oggetti POCO puri.
Service1Client client = new Service1Client(); int orderId = 43680; Order order = client.GetOrder(orderId); Console.WriteLine(order.DueDate); // Modify order. order.DueDate = DateTime.Now; // Update order in the database. client.UpdateOrder(order);