none
WebServices : Comprimir un dataset RRS feed

  • Pregunta

  • Hola

    me gustaría saber si es posible mandar un dataset a través de un webservice comprimido.

    Tengo un webservice con un método que devuelve un dataset considerablemente grande y relentiza la aplicacción, sería posible comprimirlo ?

    Buscando he encontrado que con la opción 

    WSInstance client = WSClient.Client();
    client.EnableDecompression = true;
    

    Habilitas la compresión, pero ahora bien , tengo que instalar un IIs y configurarlo o lo puedo probar en el mismo servidor de desarrollo ?

    Voy por buen camino ? 

    hay otras opciones? 

    Gracias!

    martes, 4 de octubre de 2011 8:06

Todas las respuestas

  • Y por qué no devuelve una colección de una clase de su propia construcción?  El problema con los datasets es que incluyen el esquema de xml.
    Jose R. MCP
    martes, 4 de octubre de 2011 8:26
  •  

    Ahora cambiarlo todo me resulta un poco complicado ;)

    martes, 4 de octubre de 2011 9:57
  •  
    Como alternativa, puedes hacer esto:
     
    1.- Serializa tu DataSet a binario o a XML, según gustes.
    2.- Ya que tienes el binario (o si serializaste a XML, utiliza Encoding.GetBytes para obtener el binario de éste) utiliza GZipStream o DeflateStream para comprimir esa información:
    3.- El binario resultante de la compresión, conviértelo a representación base 64.
    4.- Retorna a tu servicio web la cadena de texto que acabas de obtener.
     
    Por último, tu cliente deberá hacer estos pasos en sentido inverso.
     
    Saludos.


    Fernando A. Gómez F.
    fermasmas.wordpress.com
    Galería de ejemplos
    martes, 4 de octubre de 2011 14:23
  • Arturn...

    Entiendo cuando dices que cambiarlo todo ahora puede ser complicado, pero mientras más avance el proyecto más complicado será... y casi que te lo puedo asegurar, cualquier truco que encuentres ahora, llegará el momento en que no te servirá...

    Si manejas grandes volúmenes de datos y usas servicios para su envío, la solución no es un DataSet... :( ya sé que esto hará que des golpes en la mesa y que cuentes hasta mil antes de modificarlo, pero al final, la mejor solución es la que te propone Jose... El objeto DataSet contiene una estructura muy compleja y de la cual seguramente usarás muy poco, serializar todo eso lleva un coste de rendimiento y enviarlo por la red, mucho más...

    Salu2


    MCTS ADO.NET, MCTS WCF, MCTS WinForm, MCTS ASP.NET, MCPD Enterprise.

    Mi perfil: My geeks
    Colaborador: www.secondnug.com
    miércoles, 5 de octubre de 2011 6:25
    Moderador
  • Puedo mandar un modelo Entity Frameworks a través de un webservice ?

     


    • Editado arturn00 miércoles, 5 de octubre de 2011 8:19
    miércoles, 5 de octubre de 2011 8:19
  • me respondo a mi mismo.

    Gracias al código de este otro  http://social.msdn.microsoft.com/Forums/en-GB/asmxandxml/thread/aec6833b-d74c-4823-bd6d-5d3b1bd0faf3

    he encontrado la solución :D

     

    En el servicio 

     [WebMethod]
        public Byte[] GetDataSet() {
            
            DataSet ds = new DataSet();
    
            DataTable dt = new DataTable("T1");
    
            DataColumn c;
            for ( int i=0;i<3;i++)  {
                c = new DataColumn("C"+i, typeof(String));
                dt.Columns.Add(c);
            }
    
            for (int i = 0; i < 100; i++) {
                
                DataRow r = dt.NewRow();
                r[0] = "AA";
                r[1] = "BB";
                r[2] = "CC";
                dt.Rows.Add(r);
            }
    
            ds.Tables.Add(dt);
            return ZipDataSet(ds,true);
        }
    
        [WebMethod]
        public Byte[] ZipDataSet(DataSet ds,bool bIgnoreSchema) {
    
            byte[] bb = null;
    
            using (MemoryStream ms = new MemoryStream()) {
                using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress)) {
    
                    ds.WriteXml(zip, bIgnoreSchema ? System.Data.XmlWriteMode.IgnoreSchema : XmlWriteMode.WriteSchema);
                    zip.Close();
                }
                bb = ms.GetBuffer();
                ms.Close();
            }
            return bb;
        }
    


    En el cliente

    private DataSet UnzipDataSet(Byte[] b) {
                DataSet ds = new DataSet();
    
                using (MemoryStream ms = new MemoryStream(b)) {
                    using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress)) {
                        ds.ReadXml(zip, System.Data.XmlReadMode.Auto);
                        zip.Close();
                    }
                    ms.Close();
                }
                return ds;
            }
    
            private void GetZippedDS_Load(object sender, EventArgs e)
            {
                dataGridView1.AutoGenerateColumns = true;
    
                DataSet ds = UnzipDataSet(proxyData.GetDataSet());
    
                dataGridView1.DataSource = ds.Tables[0];
            }
    

    Ahora toca evaluar si realmente el consumo de CPU en la compresión / descompresión compensa el de transmisión de los datos.

     

    Saludos!

     

    miércoles, 5 de octubre de 2011 8:56
  • He estado haciendo algunas pruebas y he llegado a la conclusión que este método NO COMPENSA.

    He probado desde el lado cliente , donde los tiempos de transferencia de los datos mejoran considerablemente , pero el tiempo en la descompresión de los datos se come una media de casi el 50% del tiempo. Osease que te pasas el mismo tiempo recibiendo que descomprimiendo los datos.

    En cuando la comparación entre mandar el dataset en crudo o comprimido la diferencia de tiempo es casi inapreciable y en un buen numero de accesos el tiempo total entre los dos a sido superior mandando la información comprimida.

    Ahora mi pregunta , hay algún otro formato de compresión que mejore el rendimiento en la compresión / descompresión de los datos ? 

    miércoles, 5 de octubre de 2011 9:58
  • :)

    Sigo pensando que es mejor "perder" el tiempo ahora, que luego... ¿Es muy compleja la estructura que pasas en el DataSet? ¿Muchas tablas? ¿Relaciones? ¿ïndices? ¿No te compensa pasarlo a una estructura de clases propias? DTOs...

    Salu2


    MCTS ADO.NET, MCTS WCF, MCTS WinForm, MCTS ASP.NET, MCPD Enterprise.

    Mi perfil: My geeks
    Colaborador: www.secondnug.com
    miércoles, 5 de octubre de 2011 10:02
    Moderador
  • Yo también pienso que es mejor.  El XML del DataSet tiene esquemas de xml que describen las tablas y todo el xml usa namespaces, entonces el xml resulta ser bien grande.  Lo mejor es devolver un arreglo de una clase con exactamente los campos del DataSet:

    public class Dato
    {
        #region Propiedades
        public string C1 { get; set; }
        public string C2 { get; set; }
        public string C3 { get; set; }
    }
    


    El XML de eso será algo así:

    <Dato>
        <C1>AA</C1>
        <C2>BB</C2>
        <C3>CC</C3>
    </Dato>
    



    Jose R. MCP
    miércoles, 5 de octubre de 2011 14:12
  • Lo malo de este enfoque es que perderías toda la información de relaciones entre tablas, versiones de datos, llaves, etc... Pero por lo visto el OP no va a tener mucha opción...
     
    Saludos.
     
     


    Fernando A. Gómez F.
    fermasmas.wordpress.com
    Galería de ejemplos
    miércoles, 5 de octubre de 2011 21:57