Exemplarische Vorgehensweise: Serialisieren von POCO-Proxys mit WCF (Entity Framework)

Der POCO-Proxytyp kann von Windows Communication Foundation (WCF) nicht direkt serialisiert oder deserialisiert werden, da das DataContractSerializer-Serialisierungsmodul nur bekannte Typen serialisieren und deserialisieren kann. Der Proxytyp ist kein bekannter Typ. Weitere Informationen finden Sie im Abschnitt zur Serialisierung von POCO-Proxys im Thema Arbeiten mit POCO-Entitäten (Entity Framework). Um POCO-Proxys als POCO-Entitäten zu serialisieren, verwenden Sie die ProxyDataContractResolver-Klasse, um während der Serialisierung die Proxytypen den POCO-Typen zuzuordnen.

Im Beispiel zu diesem Thema wird gezeigt, wie der DataContractSerializer angewiesen wird, die ProxyDataContractResolver-Klasse in Dienstvorgängen zu verwenden. Dazu wird eine Attributklasse definiert, die für die Dienstvorgänge angewendet wird, und die intern ProxyDataContractResolver verwendet, um die Proxytypen den POCO-Typen zuzuordnen. Das Beispiel zeigt auch, wie der Attributklasse Methoden zugeordnet werden, die Teil eines Dienstvertrags in der WCF-Anwendung sind.

Die Beispiele in diesem Thema verwenden POCO-Klassen, die in Gewusst wie: Definieren von POCO-Entitäten (Entity Framework) definiert sind, sowie ein auf AdventureWorks basierendes Datenmodell, das in Gewusst wie: Anpassen von Modellierungs- und Zuordnungsdateien zur Verwendung mit benutzerdefinierten Objekten (Entity Framework) definiert ist.

So erstellen Sie ein Klassenbibliotheksprojekt, das POCO-Klassen enthält.

  1. Erstellen Sie ein neues Klassenbibliotheksprojekt mit dem Namen POCOAdventureWorksModel.

  2. Entfernen Sie die Standardquellcodedatei, die dem Projekt hinzugefügt wurde.

  3. Fügen Sie ein leeres Modell mit dem Namen AdventureWorksModel hinzu. Informationen zum Erstellen eines leeren Modells finden Sie im Abschnitt So erstellen Sie eine leere EDMX-Datei im Thema How to: Create a New .edmx File. Ändern Sie das Modell, indem Sie die Schritte in Benutzerdefinierte AdventureWorks-EDMX-Datei (Entity Framework) ausführen.

  4. Deaktivieren Sie die Codegenerierung für die EDMX-Datei. Öffnen Sie die EDMX-Datei in ADO.NET Entity Data Model Designer (Entity Designer). Klicken Sie mit der rechten Maustaste auf die Designeroberfläche, und wählen Sie Eigenschaften aus. Wählen Sie im Fenster Eigenschaften die Eigenschaft Codegenerierungsstrategie aus, und wählen Sie None aus. Wenn das Fenster Eigenschaften nicht angezeigt wird, drücken Sie F4.

  5. Öffnen Sie die Datei app.config des Klassenbibliotheksprojekts. Klicken Sie mit der rechten Maustaste auf POCOAdventureWorksModel, zeigen Sie auf Hinzufügen, und klicken Sie dann auf Neues Element.

  6. Wählen Sie im Dialogfeld Neues Element hinzufügen die Vorlage Allgemein aus, und wählen Sie dann Anwendungskonfigurationsdatei aus. Kopieren Sie den folgenden Code zwischen den configuration-Tags in der Anwendungskonfigurationsdatei. Ändern Sie, wenn erforderlich, den Data Source-Wert.

    <connectionStrings>
      <add name="AdventureWorksEntities" 
          connectionString="metadata=res://*/AdventureWorksModel.csdl|res://*/AdventureWorksModel.ssdl|res://*/AdventureWorksModel.msl;
              provider=System.Data.SqlClient;provider connection string=&quot;
              Data Source=(local);Initial Catalog=AdventureWorks;
              Integrated Security=True;MultipleActiveResultSets=True&quot;" 
          providerName="System.Data.EntityClient" />
    </connectionStrings>
    
  7. Fügen Sie einen Verweis auf die System.Runtime.Serialization-Bibliothek hinzu. Diese Bibliothek wird für die Attribute DataContract und DataMember der WCF benötigt, die für die serialisierbaren Entitätstypen verwendet werden.

  8. Fügen Sie dem Projekt eine neue Klasse mit dem Namen POCOClasses hinzu. Fügen Sie den Code von Serialisierbare POCO-Klassen auf Grundlage des AdventureWorks-Modells in die Datei ein. Dieser Code enthält den Entitätstyp und die Objektkontextdefinitionen.

  9. Kompilieren Sie das Projekt.

So erstellen und konfigurieren Sie das WCF-Projekt

  1. Erstellen Sie in der gleichen Projektmappe wie der des Klassenbibliotheksprojekts ein WCF Service Application-Projekt mit dem Namen POCOAdventureWorksService.

  2. Fügen Sie einen Verweis auf die System.Data.Entity-Bibliothek hinzu.

  3. Fügen Sie einen Verweis auf das POCOAdventureWorksModel-Projekt hinzu, in dem das Modell definiert ist.

  4. Fügen Sie der CONFIG-Datei die Verbindungszeichenfolge hinzu, damit die Entity Framework -Laufzeit die Metadaten finden kann. Öffnen Sie die Datei app.config im POCOAdventureWorksModel-Projekt, kopieren Sie das connectionStrings-Element, und fügen Sie es als untergeordnetes Element des configuration-Elements in die Datei Web.config ein.

  5. Erstellen Sie eine neue Klasse mit dem Namen ApplyDataContractResolverAttribute.

  6. Fügen Sie am Anfang der Datei die folgenden Namespaces hinzu:

    using System.Data.Objects;
    using System.ServiceModel.Description;
    using System.ServiceModel.Channels;
    
  7. Ersetzen Sie den für die neue Klasse generierten Code durch den folgenden Code:

    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.
        }
    }
    
  8. Öffnen Sie die Dienstschnittstellendatei. Standardmäßig trägt sie den Namen IService1.

  9. Fügen Sie am Anfang der Datei den POCOAdventureWorksModel-Namespace ein. Dies ist der Namespace, in dem die POCO-Typen definiert sind.

  10. Ersetzen Sie den Code, der die Dienstschnittstellendatei definiert, durch den folgenden Code:

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [ApplyDataContractResolver]
        void UpdateOrder(Order updated);
    
        [OperationContract]
        [ApplyDataContractResolver]
        Order GetOrder(int OrderID);
    }
    
  11. Öffnen Sie den Dienstquellcode. Standardmäßig trägt die Datei den Namen Service1.srv.cs (oder .vb)

  12. Fügen Sie am Anfang der Datei den POCOAdventureWorksModel-Namespace ein.

  13. Ersetzen Sie den Code, der die Dienstklasse definiert, durch den folgenden Code:

    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;
            }
        }
    }    
    
  14. Kompilieren Sie das Projekt.

So testen Sie den Dienst.

  1. Erstellen Sie eine Konsolenanwendung. Geben Sie POCOAdventureWorksTest als Name für das Projekt ein.

  2. Fügen einen Verweis auf das POCOAdventureWorksModel-Projekt hinzu.

  3. Fügen Sie einen Verweis auf den POCOAdventureWorksService-Dienst hinzu. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Verweisordner, und wählen Sie dann Dienstverweis hinzufügen aus.

  4. Öffnen Sie die Datei app.config, und fügen Sie die Verbindungszeichenfolge in die Datei ein. Öffnen Sie die Datei app.config des POCOAdventureWorksModel-Projekts, kopieren Sie das connectionStrings-Element, und fügen Sie es als untergeordnetes Element des configuration-Elements in die Datei Web.config ein.

  5. Öffnen Sie die Datei, die die Hauptfunktion enthält.

  6. Fügen Sie Anfang der Datei die folgenden Namespaces ein, in denen der Dienst und die POCO-Typen definiert sind:

    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);
    
  7. Ersetzen Sie den Code durch den folgenden Code. Beachten Sie, dass der Dienst zwar in der Lage war, POCO-Proxys zu serialisieren, der Client jedoch reine POCO-Objekte empfängt.

    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);
    

Siehe auch

Konzepte

Serialisieren von Objekten (Entity Framework)