20

Nel mio web method, ottengo un oggetto di classe di classe C# di terze parti. La classe entità non è altro che DataContract. Questa classe di entità è piuttosto complessa e ha proprietà di vario tipo, alcune proprietà sono anche raccolte. Naturalmente, quei tipi collegati sono anche DataContracts.Linq a Xml VS XmlSerializer VS DataContractSerializer

Desidero serializzare quell'entità DataContract in XML come parte della business logic del mio servizio web. Non posso usare direttamente DataContractSerializer (sull'oggetto che ricevo nel metodo web) semplicemente perché lo schema XML è del tutto diverso. Quindi l'XML generato da DataContractSerializer non verrà convalidato rispetto allo schema.

Non sono in grado di concludere l'approccio che dovrei seguire per l'implementazione. Mi veniva in mente seguenti approcci di implementazione:

  1. LINQ to XML - Questo sembra ok, ma ho bisogno di creare albero XML (vale a dire gli elementi o rappresentazione XML del l'istanza della classe) manualmente per ogni tipo di oggetto. Dato che ci sono molte classi di entità e sono collegate tra loro, penso che sia troppo lavoro per scrivere manualmente gli elementi XML. Inoltre, dovrò continuare a modificare l'albero XML come e quando la classe di entità introduce qualche nuova proprietà. Non solo questo, il codice in cui creo l'albero XML sembrerebbe poco goffo (almeno in apparenza) e sarebbe più difficile da mantenere/cambiare da parte di qualche altro sviluppatore in futuro; lui/lei dovrà guardarlo così da vicino per capire come viene generato quell'XML.

  2. XmlSerializer - posso scrivere le mie classi di entità che rappresentano la struttura XML che voglio. Ora, ho bisogno di copiare i dettagli dall'oggetto in arrivo all'oggetto delle mie classi. Quindi questo è un lavoro aggiuntivo (anche per .NET quando il codice viene eseguito!). Quindi posso usare XmlSerializer sul mio oggetto per generare XML. In questo caso, dovrò creare classi di entità e ogni volta che l'entità di terze parti viene modificata, dovrò semplicemente aggiungere nuove proprietà nella mia classe. (con attributi XmlElement o XmlAttibute). Ma la gente consiglia DataContractSerializer su questo e quindi non voglio finalizzare questo a meno che tutti gli aspetti siano chiari per me.

  3. DataContractSerializer - Ancora una volta qui, dovrò scrivere la mia classe di entità in quanto non ho alcun controllo sulle terze parti DataContracts. E ho bisogno di copiare i dettagli dall'oggetto in arrivo all'oggetto delle mie classi. Quindi questo è un lavoro aggiuntivo. Tuttavia, poiché DataContractSerializer non supporta gli attributi Xml, dovrò implementare IXmlSerializable e generare l'Xml richiesto nel metodo WriteXml. DataContractSerializer è più veloce di XmlSerializer, ma di nuovo dovrò gestire le modifiche (in WriteXml) se l'entità di terze parti cambia.

Domande:

  • Quale approccio è la cosa migliore in questo scenario considerando le prestazioni troppo?
  • Puoi suggerire un approccio migliore?
  • DataContractSerializer vale la pena considerare (perché ha prestazioni migliori rispetto a XmlSerilaizer) quando la classe di entità in entrata è soggetta a modifiche?
  • Il LINQ può essere realmente utilizzato per la serializzazione? O è davvero buono per le cose diverse dalle query?
  • XmlSerializer può essere preferito su LINQ in questi casi? Se sì, perché?

risposta

9

Sono d'accordo con la risposta di @Werner Strydom.

Ho deciso di utilizzare XmlSerializer perché il codice diventa manutenibile e offre prestazioni che mi aspetto. La cosa più importante è che mi dà il pieno controllo sulla struttura XML.

Questo è come ho risolto il problema:

ho creato classi entità (che rappresentano vari tipi di elementi XML) come per la mia esigenza e passai un'istanza della classe radice (classe rappresentanti elemento radice) attraverso XmlSerializer .

uso limitato di LINQ in caso di 1: rapporto M:

Dovunque voluto stesso elemento (ad esempio Employee) molte volte sotto nodo specifico (per esempio Department), I dichiarò la proprietà di tipo List<T>. per esempio. public List<Employee> Employees nella classe Department. In tali casi XmlSerializer ovviamente aggiunti un elemento chiamato Employees (che è raggruppamento di tutti Employee elementi) nel nodo Department. In tali casi, ho usato LINQ (dopo XmlSerializer serializzare l'oggetto NET) per manipolare il (cioè XML) XElement generato da XmlSerializer. Utilizzando LINQ, semplicemente messo tutti Employee nodi direttamente sotto Department nodo e rimosso il nodo Employees.

Tuttavia, ho ottenuto le prestazioni previste dalla combinazione di xmlSerializer e LINQ.

Il rovescio della medaglia è che tutte le classi che ho creato dovevano essere pubbliche quando potevano benissimo essere interne!

Perché non DataContractSerializer e LINQ-to-XML?

  • DataContractSerializer non permette di utilizzare gli attributi XML (a meno che implemento IXmlSerializable). Vedi lo types supported by DataContractSerializer.
  • LINQ-to-XML (e IXmlSerializable) rende il codice goffo mentre crea una struttura XML complessa e quel codice farebbe sicuramente scalpore agli altri sviluppatori mantenendo o modificando il codice.

C'è qualche altro modo?

  • Sì. Come menzionato da @Werner Strydom, puoi benissimo generare classi usando XSD.exe o uno strumento come Xsd2Code e lavorare direttamente con loro se sei soddisfatto delle classi risultanti.
7

Selezionerò XmlSerializer perché è il più gestibile per uno schema personalizzato (presupponendo che tu abbia l'XSD). Una volta completato lo sviluppo del sistema, testarne le prestazioni nella sua interezza e determinare se la serializzazione XML sta causando problemi. Se lo è, puoi sostituirlo con qualcosa che richiede più lavoro e testarlo nuovamente per vedere se ci sono dei guadagni. Ma se la serializzazione XML non è un problema, allora hai un codice gestibile.

Il tempo necessario per analizzare un piccolo snippet di dati XML può essere trascurabile rispetto alla comunicazione con il database o con i sistemi esterni. Sui sistemi con una grande memoria (16 GB +) è possibile che il GC rappresenti un collo di bottiglia in .NET 4 e versioni precedenti (.NET 4.5 cerca di risolverlo), soprattutto quando si lavora con insiemi di dati e flussi molto grandi.

Utilizzare AutoMapper per mappare oggetti creati da XSD.EXE alle entità. Ciò consentirà la modifica della progettazione del database senza influire sul servizio web.

Una cosa interessante per LINQ to XML è XSD validation. Tuttavia, questo influisce sulle prestazioni.

1

Un'altra opzione è utilizzare LINQ e Reflection per creare una classe generica per serializzare l'oggetto in XML. Un buon esempio di questo può essere trovato a http://primecoder.blogspot.com/2010/09/how-to-serialize-objects-to-xml-using.html. Non sono sicuro di come debba essere il tuo XML alla fine della giornata, ma se è abbastanza semplice, questo potrebbe fare il trucco. Non avrebbe bisogno di apportare modifiche come le vostre classi di entità aggiungere le proprietà/rimuovere/cambio, e si potrebbe usare questo in tutti gli oggetti (e altri progetti se conservato in una DLL di utilità).

+0

Grazie per aver condiviso il collegamento. La soluzione fornita non è utile per il mio problema ma ha aiutato a conoscere un altro modo per usare LINQ! – Learner