Puntos de datos

Herramientas fantásticas (y gratuitas) para Entity Framework

Julie Lerman

Julie LermanAhora que Entity Framework es un código abierto, la comunidad de desarrollo es capaz de contribuir con código en entityframework.codeplex.com. Pero no se limite a buscar herramientas y extensiones. Hay otras herramientas geniales, tanto comerciales como creadas por la comunidad, que pueden ayudarle a lograr más con Entity Framework. En esta columna, quisiera destacar algunas de estas herramientas y extensiones provenientes de la comunidad. Son todas gratuitas y están disponibles a través de la galería de Visual Studio (para extensiones IDE) o NuGet (para bibliotecas de código). Incluso algunas provienen de miembros del equipo de Entity Framework, que corresponden a proyectos personales y no oficiales.

EntityFramework Reverse POCO Code First Generator

Todavía hay quien cree que el flujo de trabajo de Database First es el único posible para crear un modelo para Entity Framework a partir de una base de datos existente. Ese flujo de trabajo en particular crea un archivo EDMX, que le permite interactuar con su modelo en un diseñador. Usar el diseñador también hará que dependa de un generador de código para crear las clases de su entidad. Pero es posible usar Code First de EF con una base de datos preexistente, gracias a las herramientas de ingeniería inversa. Actualmente, existen tres formas de lograrlo. Mi favorita es esta plantilla: EntityFramework Reverse POCO Code First Generator por Simon Hughes (efreversepoco.codeplex.com). Para ser justos, las otras dos son herramientas creadas por Microsoft que he usado ampliamente. Una es una característica de EF Power Tools Beta, que puede ver en acción en la publicación de mi blog de mayo de 2011 en bit.ly/1ky2SAJ. La otra es una mejora de EF Designer para Visual Studio que se publicó en Entity Framework 6.1 Tools for Visual Studio. EF Designer ahora incluye un método visual para crear POCO a partir de una base de datos existente y resuelve un problema que me hizo sufrir durante mucho tiempo, gracias a que permite seleccionar qué tablas incluir en un modelo. Demostré esta característica en la publicación de mi blog de febrero de 2014 en bit.ly/1rOqUv4.

La plantilla de Hughes se publicó por primera vez en CodePlex en octubre de 2012 y tenía la capacidad de seleccionar subconjuntos de una base de datos desde el principio. De hecho, la herramienta parece ofrecer todas las características que esperaba se agregarían o mejorarían en EF Power Tools y en el nuevo EF 6.1 Designer. Y no soy la única que cree esto: Mientras escribo esta columna, se han producido casi 77.000 descargas de EntityFramework Reverse POCO Code First Generator.

Puede instalar la plantilla mediante la característica Extensiones y Actualizaciones de Visual Studio y tener acceso sin conexión para proyectos futuros, o puede usarla directamente desde la web cuando quiera generar POCO desde una base de datos. Antes de agregar la plantilla, debe agregar Entity Framework al proyecto y especificar de manera explícita la cadena de conexión de la base de datos en el archivo de configuración, porque la plantilla se basa en ellos. Una vez que tiene EF y la cadena de conexión, inicie la plantilla. Para ello, agregue un nuevo elemento a un proyecto en Visual Studio. Si ya instaló la plantilla, la encontrará en Installed; de lo contrario, abra la sección Online. Observe que no he filtrado las plantillas en la Figura 1, pero EntityFramework Reverse POCO Code First Generator se encuentra en la parte superior de la lista ordenada por elementos más populares. Me impresionó mucho esta posición.

Obtención de EntityFramework Reverse POCO Code First Generator
Figura 1 Obtención de EntityFramework Reverse POCO Code First Generator

Al seleccionar este elemento, se genera un nuevo archivo de plantilla database.tt en el proyecto. La plantilla tiene una gran variedad de configuraciones con valores predeterminados ya aplicados. Puede ver una porción del archivo de plantilla en la Figura 2, que muestra algunas de las configuraciones más sencillas que puede usar para afectar al código generado. El valor ElementsToGenerate le permite controlar los tipos de clases que se generan (POCO, contexto, configuraciones fluidas, UnitOfWork). Una ventaja de esta configuración es que puede generar distintos elementos para diferentes proyectos. Puede controlar los espacios de nombres y cómo se nombran los tipos. Puede generar algunas clases básicas de Windows Communication Foundation (WCF), etc. Las configuraciones también le permiten especificar qué tablas de bases de datos deben incluirse o excluirse mediante Regexes para especificar los patrones de nombres de tablas o vistas. En mi opinión, poder especificar los objetos ha sido una característica importante. No obstante, ahora que EF6.1 Designer admite la selección visual de los objetos de la base de datos para crear un modelo Code First, en comparación, especificar los nombres de objetos en el archivo .tt me parece un tanto torpe.

Una sección del archivo de configuración de EntityFramework Reverse POCO Generator
Figura 2 Una sección del archivo de configuración de EntityFramework Reverse POCO Generator

Otra ventaja significativa que tenía Reverse POCO Code First Generator sobre la función de ingeniería inversa de EF Power Tools era el rendimiento. Sin embargo, el nuevo EF6.1 Designer acelera la generación de código de manera espectacular, así que ya no es un factor determinante para mí. No obstante, Reverse POCO Code First Generator tiene tantas nuevas características (como valores predeterminados para las columnas y valores predeterminados para propiedades) y maneras de personalizar la forma en que se generan las clases (por ejemplo, al especificar qué tipo de colección debe usarse para las propiedades de navegación) que aún me gusta. Tan solo desearía poder fusionarla con EF Designer.

Hay tanto en esta plantilla que, en lugar de enumerar aquí todas sus funciones, voy a indicarle que consulte la documentación y el vídeo de demostración de 30 minutos (reversepoco.com) para que pueda tener un comienzo excelente con esta plantilla. También verá que Hughes ha aceptado contribuciones al proyecto en CodePlex. Algo importante a tener en cuenta es que EntityFramework Reverse POCO Code First Generator actualmente funciona con SQL Server y SQL Server CE. EF6.1 Designer funciona con estas bases de datos y cualquier otro proveedor de bases de datos que se haya actualizado para trabajar con EF6.1. Me han dicho que la próxima versión importante (v3) del generador de Hughes tendrá la capacidad de aplicar ingeniería inversa en otras bases de datos, como Oracle, MySQL, etc., de la misma forma que lo hace EF6.1 Designer.

Utilidades de Entity Framework

La siguiente biblioteca que voy a destacar está a cargo de Mikael Eliasson en GitHub (bit.ly/UeWHGW). Puede aprovechar las utilidades en sus proyectos si busca EFUtilities en NuGet.

Este conjunto de utilidades se centra en el rendimiento y agrega funcionalidad para algo que los desarrolladores de Entity Framework añoran desde hace mucho: la capacidad de realizar operaciones masivas (insertar, actualizar y eliminar) en la base de datos. La clase EFBulkOperation de estas utilidades funciona con DbContext, por lo que no puede usarla con ObjectContext. Si bien varios desarrolladores han atacado el problema, conozco a Mikael desde hace un tiempo así que naturalmente me sentí atraída por su oferta. En el sitio de CodePlex para Entity Framework también se puede ver la discusión sobre los mejores enfoques para incorporar las operaciones masivas a la API nativa.

La utilidad le permite escribir consultas LINQ en la clase EFBulk­Operation a fin de ejecutar la operación pertinente. A modo de prueba, creé un modelo (con la herramienta EntityFramework Reverse POCO Code First Generator que acabo de analizar) a partir de la base de datos AdventureWorks2012. Luego creé en mi código una lista de 1.000 instancias del tipo BusinessEntity:

var entityList = new List<BusinessEntity>();
for (int i = 0; i < 1000; i++)
{
  entityList.Add(new BusinessEntity{});
}

Las inserté con el código estándar de Entity Framework y luego llamé a SaveChanges:

using (var context = new AWModel()) {
  context.BusinessEntities.AddRange(entityList);
  context.SaveChanges();
}

Esto provocó que se enviaran 1.000 instrucciones INSERT individuales a mi base de datos SQL Server, y la operación completa tardó un promedio de 6 segundos en una serie de ejecuciones repetidas. De este total, resté los tiempos de calentamiento de EF.

Luego usé la clase EFBatchOperation para insertar los mismos 1.000 objetos BusinessEntity:

using (var context2 = new AWModel()) {
  EFBatchOperation.For(context2, 
    context2.BusinessEntities).InsertAll(entityList);
}

El tiempo promedio de ejecución fue de 12 milisegundos.

Tenga en cuenta que en el código EF estándar tuve que agregar todas las instancias al contexto para que el seguimiento de cambios pudiera determinar qué SQL debía enviarse al servidor. Por otra parte, la clase EFBatchOperation no se basa en el seguimiento de cambios de EF para compilar el SQL. En su lugar, crea un DataReader, que es una clase en EFUtilities, y lo transmite a la base de datos a través de la clase .NET SqlBulkCopy que se introdujo hace tiempo en ADO.NET 2.0. Me alegró que fuera así, porque ha sido siempre mi recomendación para solucionar este problema. Así que este método no solo no fuerza al contexto a realizar un seguimiento de 1.000 entidades, sino que también envía un comando único a la base de datos junto con el flujo binario de datos que se va a insertar. SQL Profiler no va a mostrar ese flujo, así que lo único que se ve en SQL Profiler como resultado del método EFBatchoperation.InsertAll es este único comando:

insert bulk BusinessEntity
  ([rowguid] UniqueIdentifier,
  [ModifiedDate] DateTime)

Una buena protección es que si el proveedor de la base de datos no tiene un método masivo, la utilidad revertirá al método predeterminado de EF para tratar la solicitud. En este caso, significaría enviar 1.000 comandos INSERT a la base de datos.

EFBatchOperation también tiene métodos para actualizaciones masivas y eliminaciones masivas, y lo que resulta ventajoso de esto es que no hay necesidad de cargar las entidades en la memoria ni en el contexto por adelantado, como sí lo haría con EF. En su lugar, aquí encontrará un ejemplo de cómo eliminaría una selección de filas de la base de datos con EFBatchOperation:

EFBatchOperation.For(context, context.BusinessEntityContacts).Where(
  p => p.ContactTypeId == 11).Delete();

Envía el SQL pertinente a la base de datos:

DELETE FROM [Person].[BusinessEntityContact] WHERE 11 = [ContactTypeID]

Los comandos de operación masiva ya ofrecen ventajas de rendimiento significativas, y ahora Eliasson está trabajando en un sustituto del método DbContext.Include para mejorar el rendimiento de la carga diligente. En lugar de aplanar los datos y desperdiciar recursos en un montón de datos redundantes en los resultados, el objetivo del método de EF Utilities es “cargar en su lugar cada colección Included como consulta independiente y luego corregir las relaciones de forma manual. El objetivo es también proporcionar filtrado, ordenación y, de ser posible, paginación de colecciones secundarias”. Para leer más sobre esta característica y estar al tanto de los avances, lea bit.ly/1hBsGf5. No pase por alto el archivo readme.md de este proyecto.

Entity Framework 6 Contrib

Entity Framework 6 Contrib es un proyecto en CodePlex Unai Zorrilla, Microsoft MVP, (ef6contrib.codeplex.com). Zorrilla ha realizado varias contribuciones al paquete Microsoft EF, como Custom Pluralization, AddRange y RemoveRange, y AddFrom­Assembly; sobre todas estas características he escrito en columnas o artículos anteriores. Zorrilla tiene un puñado de asistentes adicionales que mantiene en el sitio ef6contrib.codeplex.com, entre otros:

  • Un servicio de pluralización en español preconfigurado (que se ha incorporado al proyecto EntityFramework Reverse POCO Code First Generator que mencioné anteriormente).
  • Dos métodos más prácticos para agregar configuraciones de la API Fluent al modelo Code First en tiempo de ejecución.
  • Varias operaciones que puede usar con migraciones de Code First que no se incluyen en EF, como DatabaseCollation, GrantTablePermission y RevokeTablePermission.
  • Un inicializador que funciona con migraciones, llamado DropAndMigrateDatabaseToLatestVersion.
  • Un conjunto de tipos de analizadores de consulta que aprovechan los interceptores y los resolvedores de dependencias de EF6.

Lo que siempre me ha gustado de los aportes de Zorrilla a EF es que toma código que escribió él y que ha usado en repetidas ocasiones en su propio trabajo y lo encapsula para compartirlo con los demás. Los analizadores, en particular, son espectaculares. Puede configurar los parámetros según los cuales desea medir el rendimiento de la ejecución de la base de datos de EF y controlar en qué medida el código se ajusta a sus expectativas. También hay un analizador que comprueba las consultas no parametrizadas. Si agrega el interceptor a la clase DbConfiguration (otra característica de EF6), analizará todos los comandos de un DbContext determinado. El proyecto CodePlex tiene una serie de pruebas y muestras que le permiten explorar los analizadores, así como otras herramientas incluidas en Entity Framework 6 Contrib. La Figura 3 muestra una clase DbConfiguration de las muestras, que agrega el PerformanceInterceptor y luego especifica que debe comprobar tres de los cuatro analizadores de la colección.

Figura 3 Configuración de algunos analizadores de Entity Framework 6 Contrib

public class Configuration : DbConfiguration  {
    public Configuration() {
      this.AddDependencyResolver(new CustomResolver());
      this.AddInterceptor(new PerformanceInterceptor((msg =>
      {
        Console.WriteLine(msg.Message);
      })));
    }
    private class CustomResolver : IDbDependencyResolver{
      public object GetService(Type type, object key) {
        return null;
      }
      public IEnumerable<object> GetServices(Type type, object key) {
        // You can use here your preferred IoC container
        if (typeof(IPerformanceAnalyzer).IsAssignableFrom(type)) {
          return new List<IPerformanceAnalyzer>(){
             new ExecutionTimePerformanceAnalyzer(TimeSpan.FromSeconds(3)),
             new UnparametrizedWhereClausesPerformanceAnalyzer(),
             new TopSlowQueriesPerformanceAnalyzer(10)
          };
        }
        return Enumerable.Empty<object>();
      }
    }
  }

Según la configuración, la ventana de la consola mostrará los informes de los analizadores.

Conjunto de extensiones y herramientas de EF

Estas son apenas algunas de las herramientas que he podido aprovechar en mi trabajo. Hay otras de las que quiero asegurarme no se pasen por alto, pero no tengo espacio para profundizar en todas ellas. Erik Ejlskov Jensen tiene una lista de algunas de las extensiones más destacadas en su publicación de blog: “Entity Framework 6 (& SQL Server Compact) (5)–Entity Framework 6 Extensions” (bit.ly/SxxPc5). Esta lista incluye una versión actualizada del EF Caching Provider, que permite el almacenamiento en caché de segundo nivel para EF6 (bit.ly/UePlmU); Trackable Entities, un sustituto del obsoleto Self-Tracking Entities (trackable.codeplex.com); y algunos proyectos adicionales que resuelven la funcionalidad de las operaciones masivas. Ejlskov Jensen es SQL Server CE MVP y, además de contribuir con muchísimas funcionalidades estupendas relacionadas con SQL CE directamente a EF6, tiene una extensión de Visual Studio muy utilizada, SQL Server Compact Toolbox, que incluye muchas características con EF. Si usa SQL CE con o sin EF, la caja de herramientas es una extensión fundamental. Por último, quisiera destacar el trabajo de Jimmy Bogard en una serie de publicaciones de blog que él llama “Missing EF Feature Workarounds”, que incluye una que extiende EF6 para proporcionar filtros globales a un modelo EF y que está disponible como paquete de NuGet. Para más información sobre esto en su publicación de blog, lea bit.ly/1prZv0a.


Julie Lerman es una Microsoft MVP, mentora y consultora de .NET Framework que vive en las colinas de Vermont. Puede encontrarla haciendo presentaciones sobre el acceso a datos y otros temas de .NET a grupos de usuarios y en conferencias en todo el mundo. Su blog es thedatafarm.com/blog y es la autora de “Programming Entity Framework” (2010) así como una edición de Code First (2011) y una edición de DbContext (2012), de O’Reilly Media. Sígala en Twitter en twitter.com/julielerman y vea sus cursos de Pluralsight en juliel.me/PS-Videos.

Gracias a los siguientes expertos técnicos por revisar este artículo: Mikael Eliasson, Simon Hughes y Unai Zorrilla