Moviendo datos en WCF

Siempre que planteamos una arquitectura, se nos plantea la misma duda ¿cómo movemos los datos entre capas de la aplicación?. Pues bien, estoy liado con la arquitectura de dos aplicaciones en cierto modo similares y una vez más me enfrento a esta cuestión. Solo que esta vez, además, esta WCF de por medio, tecnología nueva en la que no cuento con la experiencia que atesoro con DCOM, Remoting o Web Servcies ‘normales’.


Así que esta vez es un poco más arduo encontrar la respuesta.


A mi siempre me a parecido una excelente opción para mover datos usar los objetos contenedores de datos que proporcionan los ‘primos’ de la familia ADO: ADO COM del de toda la vida, con su Recordset y ADO.Net con sus DataSets y sus DataTables. Son una solución comoda, rápida de implementar y simple para solucionar el problema de mover datos entre capas de una aplicación. Los Recordset del viejo ADO y su ‘serialización’ en DCOM tenian un excelente redimiento además.


Los más puristas os estareís llevando las manos a la cabeza, diciendo, ¡pero que aberración, donde estén las colecciones de objetos!. Sin duda es una opción mucho más OOP y mucho más ‘cool’, pero ¿son la solución más comoda y simple?. En mi opinión no. Tienen un problema que hacen que no sean, en la mayoría de los casos, mi opción preferida: cada vez que añades un campo, tienes que modificar varias capas de código, no vale con simplemente cambiar la SELECT. Además las colecciones no se vinculan tan bien a componentes de interfaz de usuario (aunque esto a mejorado mucho). Las ventajas son código más elegante y un pelín más simple y autodescriptivo. Los DataSet tipados son una aproximación intermedia, pero basicamente, tener que crear un nuevo contendor de datos siempre que variamos los campos que devolvemos puede llegar a ser extremadamente tedioso y poco práctico.


Con WCF los partidarios de las colecciones tienen además otro argumento a su favor: Devolver o recibir DataSets viola el principio de SOA que dice que ‘los servicios comparten esquema y contrato, no clases’. Es evidente que cuando devolvemos o recibimos DataSet estamos obligando a que los clientes de nuestro servicio sepan que es un DataSet. Pero la reglas están para romperlas, cuando hay un motivo de peso para ello. No quiero decir que este principio no sea importante, pero si estamos seguros de que nuestros servicios solo serán consumidos desde clientes .Net, devolver DataSet puede ser muy comodo.


Ahora se presentan una serie de incognitas:


¿Mejor DataSet o DataTables?


En principio, la lógica dice, que un DataTable es un objeto más ligero que un DataSet, luego parece que una buena opción es devolver DataTables en lugar de DataSet. Pero ocurre una cosa curiosa, no podemos devolver un DataTable no tipado desde un servicio. Al menos yo no he logrado que se cree correctamente el proxy de lado cliente. No he encontrado la explicación a esta cuestión, no se porque ocurre esto. En principio el DataTable es tan serializable como el DataSet en la versión 2.0 del Framework pero no lo he logrado crear un cliente que reciba un DataTable no tipado. Especulando, he llegado a la conclusión de que el framework no tiene suficiente información para serilizar un DataTable. En concreto en este artículo dicen que debemos proporcionar un esquema para los DataTable no tipados, lo que no nos separa en nada de devolver un DataTable no tipado, cada vez que añadamos un campo tendremos que modificar el esquema devuelto.


Con los DataTables tipados no hay problema, la cuestión es que no hay ganancia ninguna, pues un DataTable tipado, se serializa exactamente igual que el DataSet tipado que lo contiene. Vamos, que los bytes que se mueven son los mismos. Para averiguar esto, simplemente he enchufado el Ethereal, un sniffer de red, para ver cuantos datos se movian.


¿Cómo son de eficientes moviendo datos los DataSet en WCF?


Se puede reformular esta pregunta a ¿Cómo de eficiente es la serialización de los DataSet en WCF?. La verdad es que no mucho. Este es el aspecto de un DataSet construido sobre la tabla Address de la base de datos AdventureWorks, cuando se devuelve desde un servicio que usa netTCPBinding, y por tanto el enconding binario.


…… net.tcp://pc065:8383/DataService…
.
…Q/http://tempuri.org/IDataService/GetTypedDataSet net.tcp://pc065:8383/DataServiceV…s…a.V.D
…..D..M…t.^J…>.5.aD,D*…D…….V…xsi)http://www.w3.org/2001/XMLSchema-instance..xsd http://www.w3.org/2001/XMLSchema@.GetTypedDataSet..http://tempuri.org/…
…..z7http://tempuri.org/IDataService/GetTypedDataSetResponse.GetTypedDataSetResponse.http://tempuri.org/.GetTypedDataSetResultV…s…a.V.D
…..D..M…t.^J…>.5.aD…….V.B.
.B.A.xs.schema..id..AddressDataSet..targetNamespace.%http://tempuri.org/AddressDataSet.xsd..attributeFormDefault..qualified..elementFormDefault..qualified..xs http://www.w3.org/2001/XMLSchema..mstns%http://tempuri.org/AddressDataSet.xsd.%http://tempuri.org/AddressDataSet.xsd..msdata$urn:schemas-microsoft-com:xml-msdataA.xs.element..name..AddressDataSet..msdata.IsDataSet..true..msdata.UseCurrentLocale..trueA.xs.complexTypeA.xs.choice..minOccurs…maxOccurs..unboundedA.xs.element..name..AddressA.xs.complexTypeA.xs.sequenceA.xs.element..name..AddressID..msdata.ReadOnly..true..msdata
AutoIncrement..true..type..xs:int.A.xs.element..name..AddressLine1A.xs
simpleTypeA.xs.restriction..base..xs:stringA.xs.maxLength..value..60….A.xs.element..name..AddressLine2..minOccurs.A.xs
simpleTypeA.xs.restriction..base..xs:stringA.xs.maxLength..value..
60….A.xs.element..name..CityA.xs
simpleTypeA.xs.restriction..base..xs:stringA.xs.maxLength..value..30….A.xs.element..name.
PostalCode..minOccurs.A.xs
simpleTypeA.xs.restriction..base..xs:stringA.xs.maxLength..value..15….A.xs.element..name..Phone..minOccurs.A.xs
simpleTypeA.xs.restriction..base..xs:stringA.xs.maxLength..value..25….A.xs.element..name..StateProvinceID..type..xs:int..minOccurs..A.xs.element..name..CountryRegionC
ode..minOccurs.A.xs
simpleTypeA.xs.restriction..base..xs:stringA.xs.maxLength..value..3….A.xs.element..name..ModifiedDate..type..xs:dateTime.A.xs.element..name..rowguid..msdata.DataType.XSystem.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089..type..xs:string……A.xs.unique..name..Constraint1..msdata
PrimaryKey..trueA.xs.selector..xpath…//mstns:Address.A.xs.field..xpath..mstns:AddressID….A.diffgr.diffgram..diffgr)urn:schemas-microsoft-com:xml-diffgram-v1..msdata$urn:schemas-microsoft-com:xml-msdata@.AddressDataSet.%http://tempuri.org/AddressDataSet.xsd@.Address..diffgr.id..Address1..msdata.rowOrder.@.AddressID.@.AddressLine1.
1970 Napa Ct.@.City..Bothell@
PostalCode..36903@.Phone..819-555-0175@.StateProvinceID..79@.CountryRegionCode..US @.ModifiedDate..2002-12-12T11:37:20.187+01:00@.rowguid.$9aadcb0d-36cf-483f-84d8-585c2d4ec6e9.@.Address..diffgr.id..Address2..msdata.rowOrder.@.AddressID..2@.AddressLine1..9833 Mt. Dias
….Resto de DataSet hasta 6,2 MB…..

Llama la atención que se incluye una gran cantidad de metadatos. Lo primero que se pasa por la cabeza es quitar esos metadatos, para disminuir el tamaño de los datos que se ponen en la red, estableciendo la propiedad SchemaSerializationMode del DataSet a ExclueSchema, pero esto para mi sorpresa ¡no tienen ningún efecto sobre la serialización del DataSet en WCF!. En Remoting y Web Services esta propiedad tenía un efecto radical sobre el rendimiento.

El problema se recrudece cuando usamos un binding basado en Http, entonces el enconding es XML y por lo tanto tenemos un tamaño de los datos serializados mucho mayor, unos 11Mb frente a los 6,2Mb que teniamos antes. Podeís ver como aparecen un motón de etiquetas XML con metadatos en la captura adjunta.

 

Resumiento los DataSet son muy comodos, pero no son lo más eficiente de mundo, sobre todo cuando se usa encoding XML. La situación es más complicada por la incapacidad de retirar los metadatos. En cualquier caso la comodidad y la sencilled pueden a veces tener más peso que el rendimiento sobre todo si este es aceptable. Devolver 20000 filas y cargarlas en un grid, tarda menos de 2 segundos en una red local.


De todos modos que casi 20000 filas, ocupen 6,2Mb en el mejor de los casos, solo deben hacernos pensar una cosa: es una pésima idea devolver 20000 registros desde un servicio, en un DataSet o en una colección de objetos o por SMS.


Por cierto, un artículo muy recomendable sobre la serialización en WCF: Serialization in Windows Communication Foundation

31 comentarios sobre “Moviendo datos en WCF”

  1. Estoy totalmente deacuerdo contigo, no hace mucho discutia con Miguel Jimenez la utilización de datareaders, datatables e incluso dataset como objetos de datos, despues de diseñar toda la capa utilizando codedom para generar las estructuras de clases, conjuntamente con funciones de reflexión todo ello mezclado con generics y otras funcionalidades, sigo pensando que muchas veces la utilización de un datatable o un datareader, sin ser tan eficaz como lo anterior, puede ahorrarnos muchas lineas de código y dolores de cabeza, creo que a veces nos olvidamos el fin de las aplicaciones intentando desarrollar la mejor solución, y la complicamos mas, sin pararnos a pensar que muchos de estos objetos, nos aportan todo lo necesario para trabajar con datos.
    Solo os queda esperar un poco al Entity Data Model de Microsoft que aportara soluciones y mejorara el rendimiento en este tipo de procesos.

  2. Perdonand que haga un post que no viene a cuento, pero me podría decir que tiene que hacer uno para tener un blog aquí? He escrito en dos ocasiones a usted (Rodrigo) y no ha recibido ninguna contestación. Si es que no se puede por no ser «conocido», con que me lo digan es suficiente y buscaré otro sitio. Pero agradecería una respuesta.

    Gracias.

  3. Exacto! Entity Data Model…

    ¿Que os parecería si os propusiera LINQ y el EDM, tal y como Juan comenta? ¿Porque no trabajar con objetos XLINQ y DLINQ en determinadas circunstancias en las que el peso de los datos nos importa? Es más, si que es verdad que con los DataSets tienes una cantidad de funcionalidades, estado de los datos, consultas, representación Modelo-Entidad bien plasmada, constraints, hasta incluso ahora con 2.0 el mismo DataSet goza de capa de acceso a datos integrada (De la cual no estoy muy de acuerdo en utilizar. A mi modo de ver tiene que existir siempre una arquitectura bien desacoplada i diferenciada en capas…), pero todos sabemos de que cojean los DataSets y es el peso que conllevan para ser transportados.

    Además, tenemos que tener en cuenta que LINQ es una tecnología que va a más, aparte de iniciarse como un conjunto de funcionalidades y integración del lenguaje de consulta para cualquier conjunto de colecciones de objetos (Languaje Integrated Query…), Linq nos introduce, y realiza la primera aproximación real al mundo de los ORM (Object Relational Mapping) o EDM (Entity Data Model) con vNext, de una forma bien estructurada y orientada a objetos en plataforma .NET.

    Además todos conocemos que el paso de un objeto Linq a dataset o dataset tipado es increíblemente sencillo, dicese de IQueryable.

    Además de que existe la posibilidad de mapear la estructura relacional de la base de datos de forma rápida i sencilla: Northwind nor = new Northwind(). También es posible arrastrar del explorador de servidores las tablas de la misma manera que los datasets en un diagrama de clases y crear relaciones entre los objetos.

    Creo que es un candidato muy serio a tener en cuenta para poder trabajar en entornos SOA en los cuales se necesite mejorar el rendimiento de comunicación entre servicios. Que mejor manera de hacerlo que utilizando colecciones de objetos con tipos simples que pesan bastante menos y después en cada capa de negocio de cada servicio trabajar indistintamente con DataSets tipados o objetos Linq según se precie.

    Saludos!!!

  4. Como siempre Rodrigo muy buen artículo!!!

    Yo he empezado hace poco a desarrollar con ASP.NET 2.0 y la verdad es que me gusta la manera de trabajar con DataSet, DataTables y TableAdapters por la facilidad con la que se desarrollan aplicaciones y lo comodo que me resulta su mantenimiento.

    Salu2

  5. Hola Rodrigo,

    Veo que no era el único que defendia el uso del DataSet o la familia ADO para encapsular los datos entre capas. Pero cuando te hablan de SOA entonces la batalla esta perdida! Yo se que trabajar con DataSets es algo comodisimo, donde vas a encontrar objetos serializables preparados para contener cualquier tipo de datos independientemente de cual sea su fuente… pero claro, si le pasas un DataSet a una aplicación JAVA creo que te dirá que te estas equivocando de destino. Espero que puedas dar algún consejillo para poder establecer un criterio a la hora de legir mis herramientas tanjibles de trabajo diario ante los desafios como SOA y SaaS. Yo no soy arquitecto, pero espero algún día llegar a alcanzar esa menta y en mi cabeza algo no para de decirme: ¿Porque lo llaman SOA si quieren decir Web Servcies (WS que es más ‘Cool’? ¿Y que de elementos físicos esta compuesto un ‘Bus de Datos’ algo de lo que siempre se habla en esto del SOA? ¿Realmente con WCF ya no tengo que preocuparme del método de comunicación (WS o Remoting) entre capas de arquitectura?¿Es posible el envio de datos binarios no serializados en una aproximación a SOA? Muchas pregunta y poco tiempo para contestarlas…

    PD: Benja que a ver si te animas y nos haces un Mod .NET 2.0 de LINQ!

    Saludos.

  6. Leo los comentarios y lo que leo entre líneas es lo siguiente: No es nada elegante eso de usar DataSet para mover datos, en el futuro tendremos tecnologías que harán este tema mucho más facil.

    ¿Pero en el presente?. Mis arquitecturas las tengo que definir hoy.

    Por cierto, no olvideís que pongo como condición que el cliente sea .net. No estoy hablando de SOA en un sentido estricto, sino de aplicaciones distribuidas en entorno .net, y de mantener la arquitectura simple y mantenible.

    Generalmente prefiero evitar la necesidad de tener que hacerme un ORM o usar uno de terceros. El paso de relacional a orientado a objetos siempre es un salto gordo (impedancia realcional objetos, lo llaman los gurus pedantes). Usando DataSets me ahoro este problema.

    Es más si nos ponemos puristas, y queremos ser totalmente SOA, las colecciones de objetos tampoco son la mejor solución. Antes prefiero devolver un ‘churro’ XML, facilmente construible desde un DataSet (usando WriteXml y métodos similares) o si me apuraís, utilizar JSON. Vamos que no hay nada más interoperable que devolver un string. Eso si, no es lo más eficiente del mundo.

    No me hableís de LINQ o de EDM, cuando los tenga, si solucionan mis problemas los usaré. De hecho las dos son tecnologías prometedoras, no cabe duda, pero aun queda un poco de tiempo para que estén disponibles.

  7. En mi opinión, no creo que usar DataSets sea una solución más cómoda que usar Entidades. De hecho, el uso de DataSet en aplicaciones que superan las 20 o 30 clases se convierte en un autentico infierno, prácticamente imposible de mantenar (podría ser que yo no hubiera usado las herramientas adecuadas). Yo, normalmente, desarrollo usando como herramientas motores de persistencia y generadores de código (en mi caso Gentle.NET y MyGeneration). Y al menos desde mi experiencia el desarrollo se agiliza.

    Desde luego, serializar colecciones de 20000 objetos también es bastante costoso. Pero ahora estamos realizando comparativas entre herramientas y no entre «metodologías».

  8. Hola Rodrigo!

    Yo soy defensor de usar objetos de transferencia de datos (DTOs o VOs). Ya que estás usando .NET 2.0, puedes hacer el binding directamente a los objetos, y si quieres añadir campos, al estar pasando un objeto los interfaces se mantienen iguales.

    Además, siendo realistas, si metes campos nuevos, usando datasets no sólo tocas la query. Si ese campo influye en la lógica de negocio, la tendrás que modificar (al igual que con un objeto). Si influye en la capa de presentación, la tendrás que modificar (igual que con un objeto). A parte de la query, que la tendrás que modificar también.

    En serio, no veo tanta ventaja al uso de los DataSets, además de que son «pesados» para las transmisiones… (será que no los uso bien, que también puede ser 😉 )

  9. fravelge, supongo que estás hablando de usar DataSet tipados.

    Si usas DataSet no tipados, no tienes el problema de la explosión de DTOs (sean estos colecciones o DataSet tipados). Ese problema es un dolor de cabeza en proyectos grandes, tener que generar un nuevo DTO o modificar uno siempre que añades un campo a una consulta es un coñazo. Cuanto más código tocas más código rompes.

    Como bien comentas tú, para que esto sea llevadero, tienes que utilizar un motor de persistencia o un generador, en mi opinión ambas soluciones complican la arquitectura sin aportar nada más que ‘elegancia’. Prefiero que mi arquitectura sea simple y use cuantas menos herramientas externas (lease generadores o ORMs) mejor, a que sea compleja y elegante.

    Además, tengo otro factor en contra de los generadores y los ORMs: Me gusta escribir mis propias sentencias SQL y mis propias tablas y saber donde se encuentran. El 80% del rendimiento de una aplicación guiada por datos esta en buenas tablas, buenos índices y buenas consultas. He visto muchas guarradas realizadas por ORMs y generadores.

    No niego que en algunos casos agilicen el desarrollo y que puedan ser una solución válida, pero tiendo a desconfiar. Para usar un ORM, o un generador, o cualquier tipo de Wizard tengo que haberlo hecho yo o que entenderlo a fondo y muchas veces el esfuerzo no compensa.

    Conste que estoy hablando de aplicaciones grandes en las que la escalabilidad es un factor muy importante.

    En cualquer caso, creo que esto es principalmente una cuestión de gusto o de estilo. Hay grandes aplicaciones, que dan un servicio optimo, construidas con cualquiera de las dos aproximaciones.

    Saludos y gracias por tus comentarios!!!

  10. Augusto me gustaría responderte una cosita:

    «Ya que estás usando .NET 2.0, puedes hacer el binding directamente a los objetos»

    Desde que estoy usando ASP.NET 2.0 en casa porque en el curro parece ser que no se animan todavía, yo construyo el DAL con DataSet Tipado (Facil y sencillo como dice el de bricomanía) ,luego me creo la BBL para crear el negocio (Si un campo debe ser mayor que 0, si esto lo otro lo que sea…) utilizando los TableAdapters del DAL para devolver los datos y ademas extiendo el DAL de una manera simple (si necesito controlar algún campo del datarow, o si necesito devolver mas datos) y luego hago el binding de la capa de presentación directamente a los objetos de la BBL. Como ves utilizo las 2 cosas y va fenomenal, pero efectivamente como dice Rodrigo esto es cuestión de gustos o costumbres.

    Salu2

  11. Yo siempre he estado a favor de un punto medio. Es precisamente lo que estaba intentando plantear.

    ¿Por qué solamente DataSets tipados y por qué solamente LINQ?

    Vamos a ver, ¿por qué razón voy a usar un DataSet para devolver 100.000 registros que solamente van a servir para ser mostrados en una lista y no van a ser tratados con ningún tipo de lógica? Siempre se ha hablado de DataReaders como objetos muchíssimo más eficientes «PARA ESTOS ESCENARIOS EN CONCRETO», en cambio cuando necesitas tratar los datos con algo más de lógica de negocio, o, es más, cuando tu aplicación tiene muchíssima concurrencia y necesitas augmentar la escalabilidad prefieres usar DataSets en lugar de DataReaders.

    Pues exactamente planteo lo mismo. ¿Quieres ser ágil? DataReader o Objetos LINQ. ¿Queremos además poder hacer consultas entre colecciones de objetos? También puedes hacerlo con LINQ. ¿Queremos además bindar objetos a las Views y Controls? Tambíen podemos usar colecciones de objetos.

    Pero no hay que negar que la potencia de los DataSets es brutal. La facilidad de uso también y las capacidades que nos aportan para manejar el estado de los datos y su consistencia es muy buena.

    Por ese motivo exiten las funcionalidades «LINQ to DataSets» y «DataSets to LINQ», porque precisamente voy a querer no solamente escojer la manera en cómo tratamos los datos, sino también, cual es la mejor manera de integrarlos en arquitecturas Saas y SOA mejorando notoriamente el rendimiento.

    Es tan sencillo como dotar a la capa DAL de una factoría que te permita escojer el tipo de datos sobre el que vas a trabajar ( generics estaría muy bien también para potenciar esto y crear constraints de tipos a aceptar ) y a partir de ahí gestionar estos objetos en base a sus capacidades, ya sea para comunicación entre servicios, ya sea para tratamientos de datos con estado, ya sea para operaciones CRUD sencillas.

    Saludos!!

  12. Los DataReader mantienen la conexión abierta mientras se ejecutan lo que afecta mucho a la escalabilidad. Además no se pueden serializar, no son una solución al problema de mover datos en una aplicación distribuida.

  13. Todo la razón Rodrigo en decir que el 80% del rendimiento de una aplicación al final se encuentran en optimización de consultas, así como administración del gestor de db. Pero seguramente, el porcentaje de consultas a optimizar suele ser muy pequeño (al menos en los escenarios que conozco). Un ORM, en ningún caso no impide o no debería impedir que determinada funcionalidad se ejecutase de la manera más optima posible.

    También decir, que es cierto que comprender el funcionamiento puede ser costoso. Pero la mayoría de los casos evaluando benchmark podríamos elegir uno u otro. Al igual que elegimos un entorno de desarrollo u otro.

    Simplemente mi experiencia de desarrollo con DataSet (es cierto que no he llegado a usar los tipados) fue un auténtico horror.

    (offtopic) Por último, viendo que sois conocedores de las próximas tecnologías de microsoft; me gustaría preguntaros si sabeis si en la próxima versión del framework incluiran algún ORM; o tal vez quede todo como la promesa de ObjectSpace en .Net 2.0.

    Un saludo,

    PS. Por cierto, en el post anterior me olvidé de felicitarte por el blog 😛

    fravelgue AT gmail DOT com

  14. cita: «DataSets Tipados, ORM, EDM, LINQ, ADO, Serialización, DAL, BBL, DTO, VO, SOA, SaaS…

    Menudo empacho tecnológico tiene este menú!!!»

    Con lo bien que nos había ido toda la vida con:
    10 CLS
    20 INPUT «CUAL ES TU NOMBRE?», N$
    30 PRINT «HOLA, » + N$

    Qué ganas de liarla que tiene la gente oye. Se nota que se aburren xD

  15. Me has quitado las palabras de la boca, Pablonetrix… ayysss.. que tiempos.
    Yo estoy de acuerdo con Rodrigo en casi todo. ADO y los datasets tienen la ventaja de llevar con nosotros más tiempo, los conoces mejor, el resto de las opciones… parecen campos de minas. Es un poco lo que comentas: es que esto debería de funcionar pero falla, ¿porque? ni idea, pero falla. Señores, menos pajaritos (léase LinQ) and k.i.s.s. 😉

    Ah! y creo que se les puede decir a los bloggers de geeks.ms Feliz día de los Enamorados. Porque anda que no hay poca devoción en vosotros. 🙂

  16. Sinceramente, comparto la opinión de Rodrigo de usar DataSet. Puede que no sea la forma adecuada segun SOA, pero si me parece la forma mas comoda de hacerlo. Eso si, conociendo como funciona un DataSet, hay que tener mucho cuidado de la cantidad de información que vas a mover, ya que en caso de mover mucha cantidad, sobretodo en caso de no encontrarse en una red local, el tiempo de respuesta podría ser desastroso.

    Sobre si es mas interesante usar colecciones, o DataSet; si sabemos a priori que todas las partes trabajaran sobre .NET, no veo a priori muchos problemas (teniendo en cuenta si es red local, por el volumen de información que podriamos mover), y acompañando con una buena arquitectura en capas, podemos hacer una aplicacion en la que quizas el rendimiento no sea lo mas cool, pero si hay que decir que es mas comoda.

    Un saludo. Carlos.

  17. Dos semanas de vacaciones y menudo lio de siglas montais. Cierto es que los Dataset son coomodisimos y sobre todos los tipados pero desde mi experiencia si la aplicación es pequeña y no tiene muchos usuarios los recomendaria, en el caso de una aplicación empresarial con muchos usuarios he tenido bastantes malas experiencias en el mantenimeinto y rendimiento de las aplicaciones.
    Tambien estoy con Rodrigo que yo no utilizare un ORM que no haya hecho yo o por lo menos entienda el código fuente a la perfección ya que tambien es un horror si te sales del estandar.
    Tambien es cierto que hasta que no tengamos LINQ no quiero saber nada de el a nivel de hacer aplicaciones hasta que no este en el mercado(ya me cage en .. con Atlas)
    Lo que entiendo es que debemos elegir la mejor opción para cada caso que todas son muy buenas pero para cierta problematica en concreto y nosotros tenemos la responsabilidad de elegir cual es la mejor en cada caso.

  18. En realidad el problema de transportar datatsets en ambientes de trabajo masivo y de comunicación entre sistemas separados fisicamente es un problema.

    Me gustaria si alguien conoce un sistema para hacer envio eficiente de dataset o algo parecido en Visual Studio, muchas gracias.

    P.D: Ya prove WSE, WCF, La bibliotecas de compresión de Pablo Cibraro, etc.

  19. Por mi in SOA modela no es necesario utilizar a DataTable/DataSet .
    DataTable/DataSet .
    DataTable/DataSet deben utilizarse en un desarrollo RAD
    In SOA modela es necesario utilizar a Business Entity.
    Business Entity deberán Serializable par [DataContractSerializer]

    DataContractSerializer tiene compatibilidad con [XmlSerializer] et [Serializable]., incluso IXmlSerializable

    Por especificar el formato de mensaje tu puede usar [MessageContract]
    [MessageContract] specificar SOAP Header && SOAP Body. –> compatibilidad ASMX. (Exemple SoapParameterStyle in ASMX = [MessageContractAttribute(IsWrapped=true)])

    [DataContract] por specificar el Datas

    Si quiere corresponder con mi : federico.poggio@gmail.com

  20. Crear una entidad y su colleción derivada de ella (esto en 2003, en 2005 podeis usar generics, creo… xD). Almacenar registros en la colección y hacer un for each para recorrer los registros. Calcular cuánto tarda…
    Ahora cojeis y usais un datatable donde almacenais los mismo registros de la colección. Ahora hacer un for each a las filas de esa tabla para recorrer los registros. Calcular cuánto tarda…

    Que? Sorprendidos????

    Yo si…ya tengo claro que utilizar a partir de ahora….

  21. Aúpa jorgeleon!!!

    No se cuales son los resultados de tu prueba… pero no son en absoluto relevantes. Tomar la decisión que aquí discutimos solo por lo que tardas en recorrer el conjunto de registros devuelto es como tomar la decisión que que coche comprarte mirando solo la anchura de las ruedas. Hay muchos factores relevantes que no se ven reflejados en tu prueba: que cantidad de datos viajan por la red, cuanto se tarda en construir un dataset frente a cuanto se tarda en llenar una colección, por poner dos de una larga lista…

  22. Hola a todos:

    Soy de la opinión que pasar colecciones de objetos es lo más «correcto» pero pasar datatables es más productivo.

    Tengo un monton de código funcionando con Remoting y quiero pasar a WCF funciones del tipo

    function ListaClientes(nombre as string) as datatable

    Pero el generador de proxys no genera bien el datatable en el cliente.

    Menuda cagada de proxy.
    ¿Alguna solución?

    – No quiero dataset
    – No quiero datatables dentro de un dataset tipado

    Un saludo

  23. Nostros hemos desarrollado aplicaciones a veces usando DataSets, a veces usando colecciones. Y no nos ha ido mal, los dos enfoques son válidos. Sin embargo últimamente nuestra tendencia es usar un ORM propio, generadores de código propios y generadores de vistas y procedimientos almacenados propios, y sobre todo colecciones de entidades de negocio. La razones por las que al final nos hemos decidido por las entidades de negocio son múltiples. El rendimiento es una de ellas. Nosotros usamos serialización WCF nativa, decoramos las entidades de negocio con DataContract y las propiedades con DataMember, y proporcionamos un nombre corto a DataMember, con lo que los nombres de las etiquetas XML del documento XML resultante de la serialización son cortos, reduciendo sustancialmente el tamaño resultante. En un Dataset con WCF hay que incluir el esquema en la serialización y los nombres de los campos son tal cual, bien largos, además el DataSet se serializa en un diferenciagrama que incluye los valores actuales y los originales, todo esto hace que el DataSet serializado sea mucho más grande que la colección de entidades serializada. El ancho de banda y la memoria requeridas son valiosos para nosotros y no nos gusta desperdiciar lo más mínimo.

    Otra razón importante es que los Datasets tienen sus defectos en funcionalidad (nada es perfecto) y lo que es peor, como no los hemos hecho nosotros no lo podemos cambiar. Lo hemos intentado, hemos informado a MS de comportamientos incosistentes e indeseables de los Datasets, pero ni caso…»this is by design».. Si quieres tener el control de lo que ocurre, te lo tienes que currar tú mismo. Y a nosotros nos gusta mucho tener el control. Por ejemplo existe un comportamiento incosistente entre el evento FieldChanged y el método CancelEdit. Si tú quieres seguirle la pista a los valores actuales de los campos, para implementar una cierta funcionalidad o cierta regla de negocio, respondes al evento FieldChanged, pero si alguien llama al método CancelEdit los valores actuales vuelven a su valor original y de eso no te enteras tú, así que le perdiste la pista a los valores de los campos. Otra cosa que nos fastidia es que cuando se elimina un registro en el evento RowChanged no puedes saber qué registro se ha eliminado, el dataset te dice que como ya se ha eliminado ya no está. ¡Coño! Yo en un trigger de SQL Server tengo la tabla virtual deleted. ¡Y coño! las colecciones que implementan INotifyCollectionChanged como ObservableCollection o CollectionView y derivados, te dan acceso a los items eliminados. No hablemos de lo «pulgoso» que es el tema de las columnas calculadas … Y … que se me olvidaba .. a mi me gusta que cuando cambio una cosa por código se refelje inmediatamente en el interfaz de usuario (WinForms o WPF), pero eso no ocurre en los datasets, como la DataRow esté en modo de edición, al cambiar un campo, el control enlazado a datos no se entera. Sin embargo eso no ocurre en mis entidades de negocio que implementan el interfaz INotifyPropertyChanged.

    Sí, el dataset tiene una funcionalidad incorporada que puede ser valiosa (..jeje..), a saber, filtrado (a través de DataViews), restricciones de integridad y relaciones, ordenación (a través de DataViews). … Espera un momento … ¿No lo hace esto ya el sistema de base de datos?… Vamos a ver, si yo tengo 100000 registros y quiero ver 100, ¿Qué hago?, ¿Me los traigo todos al cliente y los filtro con los maravillosos dataviews o dejo que sea el sistema de base de datos quien los filtre?

    Otra cosa que los datasets proporcionan es el enlace a datos. En la .NET Fx 1.0 y 1.1 hacer que una colección fuera enlazable a datos de forma decente tenías que implementar el interfaz IBindingList, pero ¡Macho! ahora estamos en la .NET Fx 3.0 y aquí usamos ObservableCollection(Of MiEntidadDeNegocio) que implementa IList e INotifyCollectionChanged. Ya no tengo que implementar esos dichosos interfaces. Y por si fuera poco en .NET Fx 3.0 tengo ListCollectionView que sirve de envoltorio a mis ObservableCollections y que en cierto sentido funciona como un DataView proporcionándome ordenación y filtrado en el lado del cliente.

    El modelo basado en entidades de negocio tampoco es perfecto. Si añades un campo a una tabla tienes que añadir el campo a la entidad de negocio, y eso no es necesario si usas Dataset sin tipo, en los dataset con tipo tienes que regeneralo. ¡Pero bueno, esto es totalmente irrelevante!: la entidad de negocio se genera mediante mi generador de código, esto quiere decir que tardo muy poco en hacerlo, además no es algo que tenga que hacer todos los días. Por otra parte, cuando añades un nuevo campo, como alguien dijo anteriormente, hay muchas otras cosas más de las que preocuparse.

    Otra cuestión importante de la que sin embargo no se ha hablado aquí es el tema de la gestión de concurrencia optimista. El modelo de datasets y dataadapters incluye de serie la detección de conflictos de concurrencia. Sin embargo tal modelo no incluye la gestión del conflicto. Resulta extremadamente complicado definir una estrategia de resolución de conflictos genérica con este modelo. Nuestro modelo incluye detección y gestión de los conflictos de concurrencia basándose en timestamp. Hemos elegido timestamp por ser técnica más simple y eficiente.

    Con esto no quiero decir que los datasets haya que tirarlos a la basura, puedes usarlos, pero en mi opnión es mejor usar entidades de negocio, a no ser que no sepas qué tienes que devolver ni sepas qué campos tiene, o qué tablas usar. El Dataset y el DataAdapter son clases genéricas que pretenten servir para todo, pero nosotros preferimos los trajes a medida.

  24. Hola SqlRanger!!!

    Lo que está claro es que no hay una única aproximación que funcione en todos los casos.

    En las aplicaciones donde el modelo de objeto no cambia las entidades funcionan bien. El problema es que cada vez más aplicaciones están guiadas por metadatos o tiene un modelo de datos más o menos flexible y en ese caso lo único que funciona con comodidad son los dataset no tipados.

    Sobre el uso de ancho de banda, una ventaja de los dataset es que con mucha comodidad puedes enviar de vuelta solo aquello que ha cambiado. Esto es mucho más complejo de hacer con colecciones de objetos, aunque no imposible. Además no es cierto que haya que mandar de vuelta todas las versiones de las filas del dataset, es suficiente aceptar los cambios del dataset antes de devolverlo.

    No en todas las aplicaciones usamos dataset ni en todas colecciones de objetos. Un problema claro de los dataset que me sorprende que no hayas nombrado es que son nativos de .Net y no interoperables, este es el principal problema a la hora de usar dataset, que expones un detalle de implementación.

    La verdad es que yo soy bastante exceptico respeto a los ORM ‘standard’ pero cada vez mejoran más y creo que cada vez serán un componente más a tener en cuenta en nuestras aplicaciones, sobre todo cuando se prime productividad sobre rendimiento y control.

    En definitiva, hay muchas aproximaciones que pueden funcionar bien siempre que se consideren los problemas y ventajas de cada una. Siempre existen estrategias que permite minimizar los problemas de cada modelo y potenciar las virtudes. Quizás el único error que se puede cometer en esto es pensar que una única aproximación sirve para todas las aplicaciones.

    Un saludo y gracias por tu excelente comentario.

  25. Coincido contigo en que la forma mas comoda para un ambiente .net son los DataSet, sin embargo si se busca que tenga interoperabilidad con otros sistemas he pensaod en utilizar lo siguiente:

    List> listaResultados;
    o una implementación con una clase genérica

    Esto brindaria la interoperabilidad deseada pero que hay del tiempo de llenado de esa lista barriendo columnas y renglones?, hay alguna forma mas rápida o eficaz de transformar una tabla a un objeto como e que te planteo

    Saludos cordiales

  26. @fcorrea: La solución al problema que comentas pasa por usar un ORM, aunque siempre podrías hacerte tu un mapeo simple recorriendo los datasets. En el mundo .Net el ORM por excelencia sería Entity Framework… aunque hay otras opciones como NHibernate…
    Te recomendaría que le hechases un vistazo al libro que han escrito mis amiguetes Octavio Hernandez, Unai Zorrilla y Eduardo Quintas sobre el tema: http://geeks.ms/blogs/jalarcon/archive/2008/10/06/ado-net-entity-framework-primer-libro-en-el-mundo-sobre-el-tema.aspx

    Un saludo y gracias por tu comentario.

  27. Y si ahora quiero usar el WCF con silverlight???

    Se me va todo al traste, pq silverlight dijo adios a los datasets…

    ¿Como controlo concurrencia en ese caso?, un dataset lo haria pero… ¿silverlight?

  28. Como podrai hacer entonces si tengo que traer gran cantidad de datos(100,000) por wcf, actualmente no me deja por sus limitaciones de seguridad en el mensaje, alguien que pueda ayudar

  29. Un saludo a todos los amigos de este post. Veo que el tema es algo antiguo y quizas a estas alturas ya todos deben ser expertos en entity framework con wcf y tienen muy claro como resolver los problemas que representa la utilización de datasets en cuanto a rendimiento, asi que me limitare a decir que si se puede pasar datatables simples con wcf, para aquellos que les daba error solo tienen que asignarle un nombre al datatable y con esto se resuelve todo.

    Coincido con que los datasets son una forma muy comoda de trabajar con wcf. en lo particular yo utilizo DTO pero en objetos donde existe relacion de padre e hijos caso de una factura elaboro un dto factura pero para el detalle elaboro un dataset tipeado y lo agrego al dto como una propiedad mas. No considero sano, pasar datatables con wcf con mas de 500 registros… y de echo nunca se me ocurriria. En este caso se debe cambiar de mentalidad en cuanto a la forma de presentar la información al usurio. Mostrar 20,000 al usuario para que el recorra los datos buscando lo que necesita, no es eficiente; lo correcto sería proporcionar opciones de busqueda para que el usuario reciba solo lo que es de su interes. Lo único que se me ocurre que pueda necesitar 20,000 registros es un reporte, pero wcf no es lo adecuado, en este caso pienso que la estrategia de microsoft para resolver esto es el servidor de reportes de sqlserver, en el cual todo el procesamiento del reporte se hace en el servidor y el cliente solo recibe el reporte procesado.

Responder a anonymous Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *