none
A ver como lo hago. RRS feed

  • Pregunta

  • Hola.

    Tengo una tabla con estos campos: Código, Producto, Precio, Porciento.

    Los registros de lo tres primeros son insertados por una rutina normal con Linq. Por lo general 10 registros; dejando a su vez, el campo Porciento vacío.

    Con los datos de un DataGrid en otro proceso, es de donde obtengo los porcentajes para el campo Porciento.

    Estos datos están consecuentemente en orden como se deben ingresar al campo Porciento de la tabla.

    Alguna idea de como actualizar estos valores extraídos del DataGrid para el campo Porciento ?

    Uso VS2013, SQLserver2012 y LINQ.

    Gracias.

    lunes, 19 de enero de 2015 16:09

Respuestas

  • Un par de cosas.

    La mejor herramienta para llenar una tabla a partir de otras tablas de la base de datos es el lenguaje SQL. En este caso, como es SQL Server, lo mejor sería un procedimiento almacenado. Andar insertando y actualizando registro a registro con LINQ es extremadamente lento cuando son muchos los registros (más de unos cuantos cientos). Con T-SQL con una única instrucción se podía generar la tabla usando PIVOT.

    Si lo único que necesitas es rotar las columnas para presentación, no es necesario tener tablas intermedias que construir. Puedes construir un DataTable con los datos pivoteados a partir de una consulta sobre las tablas base sin pivotear usando el código de este artículo de CodeProject:

    Client Side MultiColumn Dynamic Pivot

    Luego puedes usar el DataTable como origen de datos para el informe. La mayoría de las herramientas de informes trabajan con DataTables.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    martes, 20 de enero de 2015 8:49
  • hola

    lo que puedo ver es que el diseño de esa tabla es incorrecta, si hubieras estudiados las 3 formas de normalizacion para diseñar base de datos sabrias que esta mal

    definir registro como columnas es incorrecto, la tabla solo deberia ser: Codreg Secuencial Materia Nota Fecha

    entonces registra

    Codreg Secuencial  Materia     Nota   Fecha

      1            1            Materia1    X      fecha

      1            2            Materia2    X       fecha

      2            1            Materia1    X      fecha

      2            2            Materia2    X       fecha

      2            3            Materia3    X       fecha

    la idea es ir registrando filas con los datos no columnas

    se puedes definir una clave compuesta con las columnas: Codreg Secuencial, pero tambien se podria modelar con una clave simple

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    martes, 20 de enero de 2015 5:32

Todas las respuestas

  • hola

    entiendo que este campo representa un valor de porecentaje, no el calculo en si mismo, o sea usando el precion y el porciento obtendrias un total, lo planteo porque los campos calculados no deberian registrar en la tabla como campo

    podrias definir el campo en la grid y luego de ingresado los valores recorrerlo para actualizar el campo

    Using conn As New SqlConnection("<connection string>")
    	conn.Open()
    
    	Dim query As String = "UPDATE NombreTabla SET porciento = @porciento WHERE @codigo = @codigo"
    	Dim cmd As New SqlCommand(query, conn)
    
    
    	For Each row As DataGridViewRow In dataGridView1.Rows
    		cmd.Parameters.Clear()
    
    		cmd.Parameters.AddWithValue("@porciento", Convert.Toint32(row.Cells("colCodigo").Value))
    		cmd.Parameters.AddWithValue("@codigo", Convert.ToInt32(row.Cells("colporciento").Value))
    
    		cmd.ExecuteNonQuery()
    	Next
    End Using

    bueno alli use sql directamente no linq, pero la idea es similar, no puse el ejemplo en linq porque n se si usas linq to sql o entity framework

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    lunes, 19 de enero de 2015 16:25
  • Gracias Leandro, pero necesito el ejemplo en Linq.

    Disculpa que no puse en cual de los dos. Pues es en Linq to SQL.

    Entiendo los analisis logicos que me haces sobre no guardar campos calculados, realmente no los hago, es que me interesa el procedimiento con linq para hacer este proceso de actualizacion, ya que he intentado hasta la frustracion y no he podido.

    Gracias.

    lunes, 19 de enero de 2015 16:32
  • la actualizacion con linq sql es similar en su estructura

    Using db As New DbContext... For Each row As DataGridViewRow In dataGridView1.Rows Dim producto = db.FirstorDefault(Function(x) x.codigo = Convert.ToInt32(row.Cells("colCodigo").Value))

    producto.porciento = Convert.ToInt32(row.Cells("colporciento").Value)

    db.SubmitChanges() Next

    End Using

    obtienes el contexto y depsues recuperas la entidad para actualizar el campo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    lunes, 19 de enero de 2015 16:41
  • tambien hay otras alternativas que no requieren que recuperes la entidad completa para actualizar un solo campos

    LINQ to SQL: how to update the only field without retrieving whole entity

    Using db As New DbContext... 
    
    	For Each row As DataGridViewRow In dataGridView1.Rows
    	 
    		Dim prod As New Producto() With { _
    			.Codigo = Convert.ToInt32(row.Cells("colCodigo").Value), _
    			.Porciento = Convert.ToInt32(row.Cells("colporciento").Value) _
    		};
    
    		db.Productos.Attach(prod)
    		db.SubmitChanges() 
    		
    	Next
    
    End Using

    o sea la idea es crear una entidad nueva y adjuntarla

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 19 de enero de 2015 16:48
  • Gracias hermano, muy acertado el codigo.


    lunes, 19 de enero de 2015 16:50
  • Leandro.

    El problema es el siguiente. Despues de implementar tu codigo, pues este lo unico que hace es a lo sumo, repetir el primer valor del campo Porcentaje.

    Y me di cuenta de que, no tengo valor de comparacion para actualizarlos (El caso del codigo el producto), no lo tengo en el segundo proceso, de modo que, no se como hacer esto.

    Si supiera como saltar de registros solamente e ingresar los datos. Pero no lo se.

    Gracias. 

    Nota, dieme si tendria que abrir otro hilo, porque ya te marque como respuesta.

    lunes, 19 de enero de 2015 16:58
  • >>no tengo valor de comparacion para actualizarlos

    pero la entidad tiene un codigo, ese es el que usas para comparar

    no entiendo porque hablas de un segundo proceso, deberias cargarlo en el grid como una columna (si quiere readonly) para tener ese dato en cada row

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    lunes, 19 de enero de 2015 17:09
  • Ok, voy a hacer la pregunta de otra manera, a ver si me explico mejor.

    Tengo una tabla que tiene:

    Codreg   Materia1 Nota1 Fecha1  Materia2  Nota2  Fecha2

    Estos valores se obtienen de una tabla maestra que los contiene. Entonces, inserto primero los campos con 1 cuyas materias tienen un código único, las del 2 por igual. El campo  Codreg es Autoincremental y no guarda relación con nada, ademas de que la tabla es de transición, ya que se borra su contenido al finalizar el proceso, pues es para presentar un informe.

    Insertar los valores para los campos 1 es fácil, pero para los campos 2, no tengo idea. En el informe deben aparecer dos cuadriculas paralelas mostrando estos datos, como representación de dos semestres distintos del mismo año.

    Gracias Leandro.

    martes, 20 de enero de 2015 3:28
  • hola

    lo que puedo ver es que el diseño de esa tabla es incorrecta, si hubieras estudiados las 3 formas de normalizacion para diseñar base de datos sabrias que esta mal

    definir registro como columnas es incorrecto, la tabla solo deberia ser: Codreg Secuencial Materia Nota Fecha

    entonces registra

    Codreg Secuencial  Materia     Nota   Fecha

      1            1            Materia1    X      fecha

      1            2            Materia2    X       fecha

      2            1            Materia1    X      fecha

      2            2            Materia2    X       fecha

      2            3            Materia3    X       fecha

    la idea es ir registrando filas con los datos no columnas

    se puedes definir una clave compuesta con las columnas: Codreg Secuencial, pero tambien se podria modelar con una clave simple

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    martes, 20 de enero de 2015 5:32
  • Hola,

    Entiendo que la presentación de las filas en columnas es sólo por un tema de informe, estaría mal modelado si fuese la estructura de una tabla según te comenta Leandro. Esto es algo que se conoce como tablas Pivot así que no veo nada malo si sólo intentas presentar un informe.

    Aún así, veo complicado que alguien pueda apoyarte en la consulta LinQ si no muestras mas detalle de tu requerimiento. Muéstranos por favor las tablas y relaciones que intervienen en este informe. Materias y Notas deben de relacionarse con alguna tabla que quizá se llame matricula, como verás son sólo especulaciones, ayudará mucho mostrar lo solicitado.

    Al tratarse de tabla pivote, podrías crear la estructura en una vista o una tabla usando t-sql y usas LinQ sólo para mostrar los resultados en el formato esperado. Sigo especulando porque incluso este planteamiento dista mucho de como inicio este hilo.

    martes, 20 de enero de 2015 6:17
  • Un par de cosas.

    La mejor herramienta para llenar una tabla a partir de otras tablas de la base de datos es el lenguaje SQL. En este caso, como es SQL Server, lo mejor sería un procedimiento almacenado. Andar insertando y actualizando registro a registro con LINQ es extremadamente lento cuando son muchos los registros (más de unos cuantos cientos). Con T-SQL con una única instrucción se podía generar la tabla usando PIVOT.

    Si lo único que necesitas es rotar las columnas para presentación, no es necesario tener tablas intermedias que construir. Puedes construir un DataTable con los datos pivoteados a partir de una consulta sobre las tablas base sin pivotear usando el código de este artículo de CodeProject:

    Client Side MultiColumn Dynamic Pivot

    Luego puedes usar el DataTable como origen de datos para el informe. La mayoría de las herramientas de informes trabajan con DataTables.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    martes, 20 de enero de 2015 8:49
  • Ahora que si me has asustado, pues se supone que Linq es otro nivel de avance con SQL, de modo que por defecto, un nuevo modelo, acompaña mejor rendimiento.

    No entiendo.

    martes, 20 de enero de 2015 17:07
  • LINQ es un nivel más de abstración. Y seguramente facilita muchas cosas, pero no todas. Esa abstracción puede  considerase un avance, sí. Pero desde luego no para el rendimiento.

    Si quieres rendimiento Entity Framework ni LINQ to SQL son lo mejor.

    Son buenos para unas cosas, pero para otras no.

    Lo más eficiente que puedes conseguir es siempre escribir SQL diréctamente, y despúes EntityLite que facilita muchas cosas, no tanta abstración como Entity Framework, pero tiene un gran compromiso con el rendimiento, cosa que Entity Framework no.

    Sobre todo cuando se trata de insertar un conjunto de registros en una tabla a partir de otras, lo mejor es un procedimiento almacenado con un INSERT INTO ... SELECT.



    Jesús López


    EntityLite a lightweight, database first, micro orm

    martes, 20 de enero de 2015 18:57
  • Muchas gracias Jesús Lopez por tu ilustración. Has sido de mucha utilidad la información pero,  ahora tengo que reestructurar mi sistema en los módulos de mas flujo de datos.

    Gracias.

    martes, 20 de enero de 2015 23:08