sábado, 31 de diciembre de 2011

Convertir de SQL a Linq


Recientemente he estado trabajando mucho con .Net y aunque ya lo he dicho antes lo vuelvo a repetir ¡La gran mayoría de las cosas no me gustan! sin embargo eh estado encontrando buenas técnologias que valen la pena aprenderlas, entre ellas el muy conocido Linq.

Una de las principales razones para usar Linq es el hecho de que es independiente de la tecnología de almacenamiento de datos que está debajo, por ejemplo les dejo una lista de los Proveedores que actualmente existen para linq aquí y aquí una página donde explican en más detalle porque linq es mejor que usar SQL directamente.

Hoy escribo este post para dejar una pequeña documentación de como transformar consultas SQL a Linq usando Linqer.

Linqer me ayudó mucho con la conversión de SQL a Linq y la recomiendo en especial cuando quieren hacer el trabajo rápidamente además que es muy buena para aprender linq aunque lastimosamente no es libre: http://www.sqltolinq.com/


Para los efectos de mis ejemplos crearé una base de datos llamada sample1 con las siguientes tablas: table_1, table_2 y table_3 y a continuación el script sql, más simple que me es posible crear con lo que tengo a mano, es muy probable que si lo desean usar tengan que hacer algunos cambios para que funcione en su DBMS (MySQL, MS SQL Server, Oracle, etc)


Bueno manos a la obra:
1. Select simple
  • SQL: SELECT * FROM table_1
  • Linq: from table_1 in context.Table_1
    select new {
      table_1.Col_1,
      table_1.Col_2,
      table_1.Col_3
    }

2. Select con condicional:
  • SQL: SELECT * FROM table_2 WHERE col_1 <= 10 and col_2 = 'something'
  • Linq: from table_2 in context.Table_2
    where
      table_2.Col_1 <= 10 &&
      table_2.Col_2 == "something"
    select new {
      table_2.Col_1,
      table_2.Table_1_col_1,
      table_2.Col_2,
      table_2.Col_3
    }

3. Select con un group by simple:
  • SQL: SELECT SUM(col_3) sumatory, col_2 FROM Table_1 GROUP BY col_2
  • Linq: from table_1 in context.Table_1
    group table_1 by new { 
       table_1.Col_2
    } into g
    select new {
      sumatory = (System.Decimal?)g.Sum(p => p.Col_3),
      g.Key.Col_2
    }
En este punto es donde Linq se pone algo complicado por la sintaxis del group by


4. Join (old style):
  • SQL: SELECT t1.col_2, t1.col_3, t2.col_3, t3.col_1
    FROM Table_1 t1, Table_2 t2, Table_3 t3
    WHERE t1.col_1 = t2.table_1_col_1 and t2.col_1 = t3.table_2_col_1

    and t1.col_1 = t3.table_1_col_1
  • Linq: from t1 in context.Table_1
    from t2 in context.Table_2

    from t3 in context.Table_3
    where
         t1.Col_1 == t2.Table_1_col_1 &&
         t2.Col_1 == t3.Table_2_col_1 &&
         t1.Col_1 == t3.Table_1_col_1
    select new {
         t1.Col_2,
         t1.Col_3,
         Column1 = t2.Col_3,
         t3.Col_1
    }

5. Inner Join (ansi join), alternativa al ejemplo anterior
  • SQL: SELECT t1.col_2, t1.col_3, t2.col_3, t3.col_1
             FROM  Table_1 t1 inner join Table_2 t2 on t1.col_1 = t2.table_1_col_1
                inner join Table_3 t3 on t2.col_1 = t3.table_2_col_1 
                    and t1.col_1 = t3.table_1_col_1
  • Linq: from t1 in context.Table_1
    join t2 in context.Table_2
          on new { Col_1 = t1.Col_1 } equals new { Col_1 = t2.Table_1_col_1 }
    join t3 in context.Table_3
          on new { t2.Col_1, Column1 = t1.Col_1 } equals new { Col_1 = t3.Table_2_col_1, Column1 = t3.Table_1_col_1 }
    select new {
      t1.Col_2,
      t1.Col_3,
      Column1 = t2.Col_3,
      t3.Col_1
    }
6. Como ultimo ejemplo un join old style que además tiene un group by
  • SQL: SELECT t1.col_2, t3.col_1, SUM(t1.col_3) sumatory
    FROM Table_1 t1, Table_2 t2, Table_3 t3
    WHERE t1.col_1 = t2.table_1_col_1
    and t2.col_1 = t3.table_2_col_1
    and t1.col_1 = t3.table_1_col_1
    GROUP BY
    t1.col_2, t3.col_1
  • Linq: from t1 in context.Table_1
    from t2 in context.Table_2
    from t3 in context.Table_3
    where
      t1.Col_1 == t2.Table_1_col_1 &&
      t2.Col_1 == t3.Table_2_col_1 &&
      t1.Col_1 == t3.Table_1_col_1
    group new {t1, t3} by new { t1.Col_2, t3.Col_1 } into g
    select new {
      g.Key.Col_2,
      Col_1 = (System.Int32?)g.Key.Col_1,
      sumatory = (System.Decimal?)g.Sum(p => p.t1.Col_3)
    }

Hay muchas otras combinaciones que podría poner pero haría este post demasiado extenso, creo que con esto tenemos suficiente para hacernos una idea de como convertir de SQL a Linq.

No puedo dejar de mencionar LinqPad que es una buena herramienta para practicar Linq y mejorar nuestro conocimiento del mismo.

Hasta la próxima.