20

En mi web method, obtengo un objeto de una clase de entidad de C# de terceros. La clase de entidad no es más que el DataContract. Esta clase de entidad es bastante compleja y tiene propiedades de varios tipos, algunas propiedades también son colecciones. Por supuesto, esos tipos vinculados también son DataContracts.Linq a Xml VS XmlSerializer VS DataContractSerializer

Quiero serializar esa entidad DataContract en XML como parte de la lógica comercial de mi servicio web. No puedo usar DataContractSerializer directamente (en el objeto que recibo en el método web) simplemente porque el esquema XML es completamente diferente. Por lo tanto, el XML generado por DataContractSerializer no se validará con el esquema.

No puedo concluir el enfoque que debo seguir para la implementación. Lo que podía pensar siguientes criterios de aplicación:

  1. LINQ to XML - Esto se ve bien, pero tengo que crear el árbol XML (es decir, elementos o representación XML de la instancia de clase) de forma manual para cada tipo de objeto. Dado que hay muchas clases de entidad y están vinculadas entre sí, creo que esto es demasiado trabajo para escribir elementos XML manualmente. Además, tendré que seguir modificando el Árbol XML a medida que la clase de entidad introduce alguna propiedad nueva. No solo esto, el código donde genero el árbol XML se vería poco torpe (al menos en apariencia) y sería más difícil de mantener/cambiar por algún otro desarrollador en el futuro; él/ella tendrá que mirarlo tan de cerca para entender cómo se genera ese XML.

  2. XmlSerializer - Puedo escribir mis propias clases de entidad que representan la estructura XML que quiero. Ahora, necesito copiar los detalles del objeto entrante al objeto de mis propias clases. ¡Así que este es un trabajo adicional (para .NET también cuando se ejecuta el código!). Luego puedo usar XmlSerializer en mi objeto para generar XML. En este caso, tendré que crear clases de entidad y cada vez que se modifique una entidad de terceros, tendré que agregar una nueva propiedad en mi clase. (con atributos XmlElement o XmlAttibute). Pero la gente recomienda DataContractSerializer sobre este y por eso no quiero finalizar esto a menos que todos los aspectos estén claros para mí.

  3. DataContractSerializer - De nuevo aquí, voy a tener que escribir mi propia clase de entidad ya que no tengo control sobre las DataContracts de terceros. Y necesito copiar los detalles del objeto entrante al objeto de mis propias clases. Entonces este es un trabajo adicional. Sin embargo, dado que DataContractSerializer no admite atributos Xml, tendré que implementar IXmlSerializable y generar Xml requerido en el método WriteXml. DataContractSerializer es más rápido que XmlSerializer, pero nuevamente tendré que manejar los cambios (en WriteXml) si la entidad de terceros cambia.

Preguntas:

  • qué método es mejor en este escenario teniendo en cuenta el rendimiento también?
  • ¿Puede sugerir un enfoque mejor?
  • ¿Vale la pena considerar el DataContractSerializer (porque tiene un mejor rendimiento sobre XmlSerilaizer) cuando la clase de entidad entrante está sujeta a cambios?
  • ¿Debería LINQ ser realmente utilizado para la serialización? ¿O es realmente bueno para otras cosas además de consultar?
  • ¿Puede XmlSerializer ser preferido sobre LINQ en tales casos? ¿Si es así por qué?

Respuesta

9

Estoy de acuerdo con la respuesta de @Werner Strydom.

Decidí usar el XmlSerializer porque el código se puede mantener y ofrece un rendimiento que espero. Lo más importante es que me da un control total sobre la estructura XML.

Esto es cómo resolví mi problema:

creé clases de entidad (que representan diversos tipos de elementos XML) como por mi requerimiento y pasé una instancia de la clase raíz (clase que representa el elemento raíz) a través de XmlSerializer .

Pequeño uso de LINQ en caso de relación 1: M:

donde quisiera mismo elemento (por ejemplo Employee) muchas veces bajo nodo específico (por ejemplo Department), que declaró la propiedad de tipo List<T>. p.ej. public List<Employee> Employees en la clase Department. En tales casos, XmlSerializer obviamente agregó un elemento llamado Employees (que es la agrupación de todos los elementos Employee) bajo el nodo Department. En tales casos, utilicé LINQ (después de que XmlSerializer serializó el objeto .NET) para manipular el XElement (es decir, XML) generado por XmlSerializer. Utilizando LINQ, simplemente puse todos los nodos Employee directamente debajo del nodo Department y eliminé el nodo Employees.Sin embargo, obtuve el rendimiento esperado por combinación de xmlSerializer y LINQ.

Lo malo es que todas las clases que creé tenían que ser públicas cuando podían ser internas.

¿Por qué no DataContractSerializer y LINQ-to-XML?

  • DataContractSerializer no permite utilizar atributos XML (a menos que implemento IXmlSerializable). Vea el types supported by DataContractSerializer.
  • LINQ-to-XML (y IXmlSerializable también) hace que el código sea torpe al crear una estructura XML compleja y ese código definitivamente haría que otros desarrolladores se rascaran la cabeza mientras lo mantenían/​​cambiaban.

¿Hay alguna otra manera?

  • Sí. Como lo menciona @Werner Strydom, puede generar clases usando XSD.exe o una herramienta como Xsd2Code y trabajar directamente con ellos si está satisfecho con las clases resultantes.
7

Seleccionaré XmlSerializer porque es el más fácil de mantener para un esquema personalizado (suponiendo que tenga el XSD). Cuando haya terminado de desarrollar el sistema, pruebe su rendimiento en su totalidad y determine si la serialización XML está causando problemas. Si es así, puedes reemplazarlo por algo que requiera más trabajo y probarlo nuevamente para ver si hay alguna ganancia. Pero si la serialización XML no es un problema, entonces usted tiene un código que se puede mantener.

El tiempo que se tarda en analizar un pequeño fragmento de datos XML puede ser insignificante en comparación con la comunicación con la base de datos o los sistemas externos. En los sistemas con memoria grande (16GB +), es posible que el GC sea un cuello de botella en .NET 4 y versiones anteriores (.NET 4.5 intenta resolver esto), especialmente cuando se trabaja con conjuntos de datos y flujos de datos muy grandes.

Usa AutoMapper para asignar objetos creados por XSD.EXE a tus entidades. Esto permitirá que el diseño de la base de datos cambie sin afectar el servicio web.

Una cosa que es genial sobre LINQ to XML es XSD validation. Sin embargo, eso afecta el rendimiento.

1

Otra opción es utilizar LINQ y Reflection para crear una clase genérica para serializar su objeto a XML. Un buen ejemplo de esto se puede encontrar en http://primecoder.blogspot.com/2010/09/how-to-serialize-objects-to-xml-using.html. No estoy seguro de cómo debe verse su XML al final del día, pero si es bastante básico, podría funcionar. No es necesario realizar cambios a medida que las clases de entidad agregan/eliminan/cambian propiedades, y puede usar esto en todos sus objetos (y otros proyectos si están almacenados en una DLL de utilidad).

+0

Gracias por compartir el enlace. La solución proporcionada allí no es útil para mi problema, pero me ayudó a conocer una forma más de usar LINQ. – Learner