Escribiendo consultas LINQ con Entity Framework (I)

25 10 2008

Linq to Entities es una nueva extensión para Linq (.Net 3.5) que hace que programar contra bases de datos sea mas fácil que nunca reduciendo los errores de impedancia en las tablas, columnas, filas de las base de datos y nuestro modelo de objetos.

El problema hasta ahora era que había distintos lenguajes para consultar información de Active Directory, Bases de datos, XML, objetos, etc. Tenias que conocer el funcionamiento y la gramática de Xpath, LDAP y muchos otros según el almacenamiento de la información. Con LINQ este problema desaparece ya que nos proporciona una tecnología para acceder a cualquiera de las tecnologías mencionadas anteriormente usando un lenguaje y gramática comunes. De esta manera nuestro código se independiza de nuestra forma de almacenamiento de datos. Hoy podemos tener la información en una base de datos y mañana lo mismo en un fichero XML, de manera que la misma consulta funcione sin cambios.

Creando un Entity Data Model

Para usar Entity Framework es necesario tener instalado el Service Pack 1 de Visual Studio 2008. Una vez instalado ya podremos ver una nueva opción en el menú Add New Item (no se como se llama esta opción en castellano, creo que es Añadir Nuevo Elemento).

Para este ejemplo voy a usar una aplicación de consola con la base de datos Northwind para que resulte todo más sencillo. Los pasos a seguir son los siguientes:

  1. Una vez creado el proyecto de aplicación de consola nos vamos al menú Project->Add New Item y seleccionamos ADO.NET Entity Data Model.

  2. Le asignamos un nombre a nuestro Data Model, por ejemplo NorthWindModel.edmx y presionamos Add.

  3. En la siguiente pantalla seleccionamos Generate From Database y damos Next

  4. En la pantalla siguiente debemos indicar la cadena de conexión a nuestra base de datos, pudiendo elegir entre una ya creada o componer una nueva. Tenemos un check para guardar dicha cadena en nuestro fichero .config de la aplicación, pudiendo cambiarle también el nombre. Una vez realizados todos los cambios pulsamos Next

  5. En la siguiente pantalla nos aparece una lista con las tablas, vistas y procedimientos almacenados. Seleccionamos Customers,Orders,Order Details y Products. Una vez añadidas pulsamos Finish y se genera nuestro Data Model.

Obtendremos algo parecido a esto:

Ejecutando consultas

Linq es un lenguaje muy parecido a SQL, la principal diferencia es que la cláusula FROM se encuentra al principio y el SELECT al final. Esto es así para que pueda funcionar correctamente el intellisense de Visual Studio. De esta manera intellisense sabe a que objeto nos estamos refiriendo y nos muestra sus propiedades según vamos escribiendo.

Un ejemplo muy sencillo:

static void Main(string[] args)

{

using (NorthwindEntities context = new NorthwindEntities())

{

var clientes = from p in context.Customers

select p;

foreach (Customers cliente in clientes)

{

Console.WriteLine(cliente.ContactName);

}

}

Console.ReadLine();

}

Explico brevemente el codigo:

  • using (NorthwindEntities context = new NorthwindEntities()) Con esta linea indicamos que vamos a usar el model que hemos creado anteriormente y gracias al using todas las operaciones se abriran y cerraran solas sin tener que preocuparnos por ello.

  • var clientes = from p in context.Customers select p; Es la query a ejecutar. Hace uso de los tipos anonimos (var). De esta manera se infiere el tipo del objeto en la parte izquierda a partir de la parte derecha. Esta consulta simplemente obtiene todos los registros guardados en Customers.

  • foreach (Customers cliente in clientes): Recorro el objeto clientes y voy mostrando el ContactName de cada uno de los objetos Customer que contiene.

Si quiesemos que nos cargase tambien los objetos de tipo Order relacionados con Customers tenemos dos opciones:

  • Cargarlos directamente en nuestra consulta usando el metodo .Include():

var clientes = from p in context.Customers.Include(“Orders”)

select p;

Se pueden encadenar los includes, pero hay que ser cuidadoso con este sistema pues puede llegar a realizar cargas muy lentas y bloquear la ejecución.

  • Cargarlo mediante codigo, de esta manera se puede cargar solamente si se cumple una condicion, comprobar si no esta ya cargado, etc.

foreach (Customers cliente in clientes)

{

cliente.Orders.Load();

}





Sobrecargar .ToString() para facilitar la depuración

16 09 2008

Muchas veces a la hora de depurar nos encontramos con que no vemos rapidamente las propiedades que nos interesan de nuestros objetos, por que hay muchas o por otro tipo de razon, o simplemente para facilitar el logeo de errores . Una buena manera de solucionar esto es sobrecargar el metodo .ToString() de nuestros objetos. De esta manera podremos personalizar los que nos devuelve de forma mas util para nosotros. Imaginemos que tenemos una clase Persona con dos propiedades: Nombre y Apellido. En este sencillo ejemplo querremos mostrar el valor de los dos campos, para ello simplemente pondremos lo siguiente dentro del codigo de nuestra clase:

public override ToString() { return “Nombre: ” + Nombre + “; Apellido: ” + Apellido; }

De esta forma pasariamos de ver esto: A ver esto otro:

A la hora de logear posibles fallos tambien nos dara mucha flexibilidad pues con solo llamar al metodo .ToString de nuestros objetos podremos tener accesibles todas sus propiedades y debidamente formateadas.





SQL Faster Paste, add-in para Visual Studio

15 09 2008

Hace poco he descubierto este add-in para Visual Studio que nos ayuda a la hora de desarrollar contra bases de datos (si no usamos Entity Framework o algo similiar como NHibernate).

A la hora de desarrollar contra base de datos tendremos que realizar consultas sql, probarlas en el analizador, llevarlas al codigo, darlas formato, parametrizar variables, etc…. Pues bien con SQL Fater Paste nos ahorramos todo (menos el tener que picar la SQL obviamente).

Para ver mas detalles mira en el blog de Chema Alonso que es donde lo encontre:  Chema Alonso

Enlace de descarga: Descargar





Yslow, complemento para Firebug

5 09 2008

Recientemente he descubierto un nuevo complemento para Firefox y Firebug. Se trata de Yslow, un añadido de firebug que nos da diversors parametros sobre la pagina web que estamos visitando. Entre estos datos destacan los consejos de rendimiento para mejorar la pagina, las estadisticas y las diversas herramienta para ver los javascript de la pagina y los css todos juntos.

Esta es la pagina principal:

Esta es la pantalla que se abre al hacer click sobre Yslow

Esta es la pantalla que se abre al hacer click sobre Yslow

Esta pestaña muestra las estadisticas de la pagina:

Muestra las diferencias entre usar cache y no usarla

Muestra las diferencias entre usar cache y no usarla

Desde esta pestaña podemos comparar los ficheros que se descargan la primera vez que accedemos a la pagina (Empty cache) y lo que se tiene que descargar una vez ya ha cacheado. Muy util para ver esos ficheros rebeldes y en los que debemos centrarnos para mejorar la velocidad de nuestras paginas.

Y para terminar la pantalla de consejos y rendimiento:

Desde aqui si nos indica el rendimiento de la pagina y como mejorarlo

Desde aqui si nos indica el rendimiento de la pagina y como mejorarlo

Nos muestra un listado de reglas que deben cumplir las paginas, ademas nos muestra en que apartados flojea la pagina actual y si haces click sobre ellos te muestra una pagina con indicaciones para corregirlos.

En resumen un gran complemento, que nos sera de gran ayuda a la hora de mejorar nuestras paginas.

Pagina de descarga: Yslow





Solucion al error: “The custom tool ‘MSLinqToSQLGenerator’ failed while processing the file …”

5 09 2008

Hoy actualizando mi equipo al SP1 de Visual Studio 2008 y del Framework 3.5 me ha surgido el siguiente error en una aplicación que en otros equipos funcionaba perfectamente:

“The custom tool ‘MSLinqToSQLGenerator’ failed while processing the file ‘App_Code\PrescripcionModel.dbml’”

Creia que algo habia fallado en la instalacion y probe a repararla, instalar ultimas versiones de los complementos y nada funcionó.

Al final simplemente tuve que borrar todas las subkeys por debajo de HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Packages en el registro y todo volvio a la normalidad.

Todo gracias a este link





Google Chrome ya disponible

2 09 2008

Google acaba de habilitar la descarga de su navegador llamado Chrome. Tiene algunas funciones interesantes como la navegacion anonima, atajos en las aplicaciones. Ya lo tengo instalado y lo estoy probando. La primera impresion es buena, pero por ahora seguire con Firefox 3. Ademas todavia no esta disponible para Mac :(

Descargar





Links interesantes sobre .Net y TFS

2 09 2008

Hoy voy a hacer una recopilacion de links a diferentes paginas que me han resultado interesantes:





Como carga Entity Framework los datos

20 08 2008

Imaginemos que tenemos una tabla Clientes y una tabla de Direcciones (un cliente puede tener varias direcciones) y generamos el modelo con el wizard de Visual Studio.

Si pedimos solo un objeto Cliente lo recibimos sin sus direcciones.

var ClienteObj = from p in context.Clintes select p where p.nombre=”Juan”;

Despues de estos cargamos los datos de las direcciones.

ClienteObj.Direcciones.Load();

Si volvemos a obtener el cliente, tambien se obtienen las direcciones sin tener que hacer el .Load() explicitamente. Porque?

Muy facil, Entity Framework cachea los datos para evitar viajes a la base de datos.  La primera vez que se pide un cliente la cache de EF (llamada ObjectStateManager) mantendra una vista del objeto que es devuelto. Al pedir las direcciones sucede lo mismo. La siguiente veces que pidamos el cliente, EF compara el key que es devuelto de la base de datos y descubre que ya lo tiene cacheado, de manera que devuelve el objeto cacheado que ya contenia las direcciones. Se puede controlar como se comporta la comparacion entre el objeto cacheado y el de la base de datos usando MergeOption al ejecutar la consulta:

http://msdn.microsoft.com/en-us/library/system.data.objects.mergeoption.aspx

Si se quiere obtener siempre los datos de la base de datos se debe usar MergeOption.NoTracking (pero EF no mantendra un registro de los cambios por lo que sera util principalmente en escenarios de solo lectura).

De todas maneras sigue haciendo una llamada a la base de datos para obtener un objeto que ya tiene en memoria. Como evitar esto? Tambien es muy sencillo usando el metodo GetObjectByKey (o su gemelo mas seguro, TryGetObjectByKey).

Esto lo que hace es buscar una entidad especifica (usando su EntityKey) primero en el objectContext, si no lo encuentra entonces realiza la llamada a la base de datos. De esta manera en el escenario adecuado nos podemos ahorra una llamada a la base de datos. Un escenario asi seria:

  • una sola entidad
  • no se necesitan datos relacionados
  • no se necesita sincronizacion con la base de datos.

Hay que tener en cuenta que si el objeto no esta cacheado, se devuelve solo ese objeto y no los relacionados. Pero si por ejemplo ya teniamos cargadas las direcciones de un cliente no cacheado y solicitamos ese cliente, de la base de datos se obtiene el cliente y las direcciones se obtienen del contexto.





Nuevos recursos para Visual Studio 2008 SP1 y EF

18 08 2008

Microsoft acaba de sacar hace poco el Service Pack 1 para Visual Studio 2008 y por supuesto al traer muchas novedades tambien han actualizado la documentacion.

Desde este enlace se pueden descargar los nuevos ejemplos para Entity Framework. Es una buena manera de ir introduciendose en esta nueva herramienta.

Por otro lado han actualizado los training kit para el SP1 de .NET Framework 3.5 y Visual Studio 2008. Contiene presentaciones, hand-on labs, demostraciones, etc todo de gran utilidad para conocer las nuevas funcionalidades. En esta pagina se pueden consultar los contenidos y desde esta otra pagina .NET Fx 3.5 Enhancements Training Kit se puede realizar la descarga del training kit.

Voy a acabar de instalar el SP1 y les echare un vistazo.





Uso de CPU en Entity Framework

17 08 2008

Jorge Roman me acaba de comentar mediante Twitter que esta teniendo problemas de CPU usando Entity Framework. He estado mirando documentacion y mirando el foro de Entity Framework parece ser que esto se da al realizar la materealizacion del modelo.

Una de las personas comentaba que tenia una base de datos de mas de 500 tablas. Tratando de ejecutar el siguiente codigo:

ObjectQuery customerQuery = myContext.Customer.Include(“CustomerType”);

List custList = customerQuery.ToList();

al llegar a la segunda linea el uso de CPU se disparaba al 100% y se mantenia constante durante 5 minutos!!!

Por lo visto esto es algo que el equipo de EF conoce y estan trabajando en ello para la version 2. De momento dan varias “soluciones”:

  • Usar solo las tablas que vayamos a necesitar. Es decir si tenemos 50 tablas y solo vamos a usar 10, incluir solo esas 10 en el modelo.
  • Crear varios modelos. Dividir nuestra base de datos en varios submodelos reduce los tiempos, ya que no sera habitual usarlos todos a la vez. (Tengo que investigar la manera de relacionarlos entre si)
  • Usar vistas precompiladas. De esta manera pasamos el coste de cpu al tiempo de compilacion. Puede ser un poco engorroso si nuestro modelo sufre bastantes cambios y hay varios desarrolladores implicados.

Como generar las vistas precompiladas:
1. Añadir un *.edmx al proyecto

2. Guardar todo

3. Click derecho en el proyecto desde el explorador de soluciones y darle a “Unload Project”

4. Click derecho otra vez y seleccionar “Edit projectname.csproj”

5. Añadir este trozo de XML antes del tag de cierre del proyecto.

<Target Name=BeforeCompile Inputs=$(ProjectDir)\Model1.edmx Outputs=$(ProjectDir)\MyViews.cs>

<Exec Command=%25WINDIR%25\Microsoft.NET\Framework\v3.5\EdmGen.exe /nologo /mode:viewgeneration “/incsdl:$(TargetDir)\Model1.csdl” “/inssdl:$(TargetDir)\Model1.ssdl” “/inmsl:$(TargetDir)\Model1.msl” “/outviews:$(ProjectDir)\MyViews.cs” />

</Target>

Cambiar las letras en negrita segun la nomenclatura usada en nuestro proyecto. Para VB hay que añadir /language:VB.

6. Recargar el proyecto

7. Compilar

8. Añadir MyViews.cs para que sea incluido en compilacion

* Esto es un traduccion de un post de Jaroslaw Kowalski.

De todas maneras tengo que seguir revisando cosas, por que no me acaban de convencer las soluciones aportadas.








Seguir

Get every new post delivered to your Inbox.