Serializzare le entità di LINQ to SQL con WCF

di Cristian Civera, in Windows Communication Foundation,

LINQ to SQL è uno strumento che semplifica e velocizza lo strato di accesso ai dati e rivoluziona anche il modo in cui questi si interrogano. In certe applicazioni, soprattutto di piccole dimensioni, è probabile che si scelga di usare le entità di LINQ to SQL per l'intera applicazione, legandosi direttamente a SQL Server. In questi casi queste entità possono essere anche usate in servizi realizzati con Windows Communication Foundation, ma purtroppo se ti tenta di eseguire un'operazione, si riceve un InvalidDataContractException. Questo perché il motore di serializzazione di WCF, basato sulla classe DataContractSerializer, richiede che la classe e tutto il ramo degli oggetti, siano marcati con l'attributo DataContract e i membri da serializzare, con DataMember.

Occorre quindi intervenire nel designer all'interno del file .dbml, sulle proprietà del DataContext, e cambiare la proprietà Serialization mode in Unidirectional, oppure con sqlmetal.exe, utilizzare l'opzione /serialization:unidirectional. Questa modifica fa si che il generatore di codice crei le classi marcandole con l'attributo DataContract, mentre le proprietà con DataMember, ad eccezioni di quelle di tipo EntityRef (one to one), per evitare referenze circolari. Inoltre, tramite tre metodi speciali OnSerializing, OnDeserializing e OnSerialized imposta una variabile boolean per variare come restituire le proprietà in fase di serializzazione. Nello specifico, con deferrer loading abilitato, le proprietà di tipo EntitySet (one to many) restituisco null invece che caricare normalmente i figli sul get della proprietà. Per caricare quindi anche le entità figlie e serializzarle è necessario specificare le DataLoadOptions per istruire il motore su quali entità caricare.
Per testare tutto, senza provare direttamente un servizio, basta utilizzare direttamente la classe DataContractSerializer.

using (NorthwindDataContext dc = new NorthwindDataContext())
{
    dc.DeferredLoadingEnabled = false;

    DataLoadOptions options = new DataLoadOptions();
    options.LoadWith<Customer>(c => c.Orders);
    dc.LoadOptions = options;

    DataContractSerializer serializer = new DataContractSerializer(typeof(Customer));
    using (XmlWriter writer = XmlWriter.Create(Console.Out))
    {
        object value = dc.Customers.First();
        serializer.WriteObject(writer, value);
    }
}

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi