EF 6:Nuevas pequeñas grandes cosas..

Creo que son ya unas cuantas entradas las que llevo con EF 6 en este blog, y eso que aún no tenemos ni la primera CTP, pero a cada nueva build que hacen podemos ver nuevas e interesantes cosas que me gusta adelantarme a escribir.

 

De entre estas nuevas cosillas me gustaría destacar estos tres nuevos métodos que he podido contribuir en sus correspondientes pull request ( addrange, removerange, haschanges )

 

AddRange

 

Como seguramente os imaginaréis, este pequeño método nos permite agregar dentro de nuestros DbSet<T> y DbSet un conjunto de elementos de una única pasada, evitando así tener que hacer las n repetitivas llamadas al método Add. Aunque esto parezca trivial, y en realidad, fuera fácil de construir con un método extensor, la verdad es que tiene un pelín más de miga, puesto que algo que podíamos hacer era aprovechar este nuevo método para evitar la detección de cambios para cada uno de los elementos de la colección a incluir.

Nota:

Como seguramente sabréis, EF realiza un proceso de detección de cambios de forma automática ( si no hemos configurado lo contrario ) en ciertos procesos, como por ejemplo en el de agregar elementos al DbSet, por lo tanto, esto podría suponer una sobrecarga en ciertos escenarios con muchas entradas en el ObjectStateManager. Si quieres saber más sobre la detección de cambios en EF, entonces nada mejor que leer del mejor, en concreto, esta serie de Arthur Vickers.

 

Al final, una vez valorado esto y agregado este nuevo método en la superficie publica de DbSet<T> y DbSet, el código queda tan liviano como vemos a continuación en el método AddRange de nuestro InternalSet.

RemoveRange

 

Bien, después de explicado lo anterior, este es de cajón, en realidad aplican los mimos argumentos con respecto a relajar la detección de cambios, por lo tanto, la implementación en nuestro InternalSet es similar a lo siguiente:

 

HasChanges

 

Este método es una pequeña ayuda para comprobar si nuestra unidad de trabajo tiene cambios pendientes, elementos agregados, borrados o modificados en la misma y no llevados aún a la base de datos. El mismo está situado en la clase DbChangeTracker y como podemos ver en el siguiente tests funcional lo tendremos accesible mediante la propiedad ChangeTracker de nuestros DbContext.

 

 

La implementación es realmente sencilla puesto que internamente ya se dispone de un método para comprobar el número de entradas en el ObjectStateManager.

 

Para terminar esta pequeña entrada me gustaría hablar de otra “gran” novedad que tenemos en las últimas builds de EF, novedad introducida por el propio equipo, en concreto por Andrew Peters (@anpete), que consiste en la posibilidad de hacer el scaffolding de las entidades mapeadas con procedimientos almacenados de forma automática. Lo mejor para explicarlo es ver un pequeño ejemplo, para ello partiremos del siguiente modelo y su correspondiente configuración:

 

Nada nuevo, o por lo menos de lo que no hayamos hablado ya, una entidad mapeada con procedimientos almacenados por medió del método MapToStoreProcedures, aplicando convenciones al no estar “configurado”. Lo nuevo en las últimas builds, le recomiendo usar los paquetes de NuGet del feed de ASP.NET Stack nightly builds, está en que las migraciones son capaces de hacer el scaffolding de estos procedimientos almacenados, por lo tanto, si ejecutaramos la creación de una migración, tal cual sigue:

 

Veríamos un resultado similar a lo siguiente:

¿Qué os parece?

 

Saludos

Unai

EF 6: Connection resiliency y azure

Seguro que de muchos es sabido que cuando trabajamos con Sql Database es posible que alguna de nuestras operaciones pueda fallar, independientemente de si usamos EF, NH o directamente con nuestro SqlClient, debido a inestabilidades de la red o problemas de back-end [si desea explorar el porque de la realidad de estos problemas le recomiendo este enlace].  Aunque en la realidad esto no es algo ni mucho menos habitual, puede pasar, y, por lo general, sino somos conscientes de ello suele dar bastantes dolores de cabeza, por lo aleatorio de los fallos. Por supuesto, hay muchos workaround para este problema, y como no, también para los que usamos actualmente EF, en cualquier de sus versiones como por ejemplo este que comenta mi buen amigo Cesar de La Torre. en un post de hace una eternidad. Con el fin de hacer  esto más sencillo para nosotros y en realidad para resolver otros posibles problema similares para este u otros motores relacionales el equipo de EF ya tiene en la rama de EF 6 nuevas funcionalidades.

Estas nuevas características se pueden concretar en los siguientes elementos:

IExecutionStrategy

Esta interfaz define el contrato para la pieza que tendrá como responsabilidad la ejecución de operaciones que potencialmente necesiten reintentarse, por ejemplo las operaciones sobre Sql Database. El contrato de esta interfaz no es nada complicado como podemos ver a continuación:

 

 

La idea básica que hay detrás de esta interfaz es poder envolver una acción en un determinado ámbito capaz de decidir si las excepciones que se produzcan son o no candidatas para reintentarse, por ejemplo porque entendemos que es un fallo de Sql Database y no relacionado con el mapeo, consulta etc…, cada cierto tiempo. Por supuesto, decidir si una excepción  de una operación implica que la operación debe repetirse es algo configurable y no fijo, cuya implementación esta marcada por una nueva interfaz, que vemos a continuación.

 

IRetriableExceptionDetector

Mediante este contrato tendremos la posibilidad de especificar que excepciones son candidatas a “resolver” por medio de reintentos, el siguiente código representa este contrato

 

 

IRetryDelayStrategy

Este es el último elemento que necesitamos, y probablemente el más sencillo puesto que tiene como única finalidad marcar el tiempo entre reintentos de operaciones fallidas.

 

 

 

Bien, ahora que ya conocemos las piezas, ya podemos entender que tenemos para Sql Database, y esto, no es más que implementaciones concretas para estos contratos que podemos “inyectar” dentro de EF .

La implementación para el trabajo de Azure, Sql Database, se basa principalmente en la clase SqlAzureExecutionStrategy, que tendremos por defecto en el proveedor de Sql Server por defecto.

Como observará, en realidad esto no tiene nada más que el marcador de tiempos, ExponentialRetryDelayStrategy, que cuyo nombre indica hace un incremento exponencial basado en la siguiente fórmula:min (minDelay + coefficient * random(1, maxRandomFactor) * (exponentialBase ^ retryCount – 1), maxDelay), y un detector de excepciones personalizado que permitirá reintentar las siguientes excepciones.

 

  • SqlException con diferentes numberos de error, revisar el código siguiente para ver los casos concretos.
  • Un TimeoutException.

 

 

Como se establece la estrategia que queremos usar? por ejemplo esta para Sql Database?, pues bien, tan simple como hacemos otras inyecciones, por medio de nuestro DbConfiguration y el método AddExecutionStrategy.

Si nos fijamos un poco veremos como lo primero que hace este método es recuperar el proveedor para el que aplica esta estrategia, buscando un atributo, DbProviderName. Una vez localizado este atributo se establece el dependency resolver con la estrategia indicada. A partir de ese momento, ya tendremos disponible nuestra estrategia de reintentos..

 

 

Bueno, esto ha sido todo, espero que os sigan gustando las novedades de EF 6 y que sigáis viendo todo lo nuevo que poco a poco vamos teniendo

Unai

EF 6: Snack Preview de MapToStoreProcedures en EF 6

Por diversas razones, que no son objetivo de este post, el mapeo a procedimientos almacenados ha sido una de los issues más votados dentro del proyecto de EF 6, y por eso, tal como estaba en el roadmap inicial, el equipo ya ha empezado a trabajar en esta característica, de la cual ya tenemos algo hecho con lo que podemos jugar. Aunque aún tengo unas cuantas preguntas sin responder del equipo, con las fuentes actuales vemos como se ha incluído un nuevo método MapToStoreProcedures dentro de nuestra bien conocida clase EntityTypeConfiguration<T>.

Como se puede ver en este pequeño fragmento, gracias a este nuevo método, tendremos la posibilidad de configurar el mapeo contra los procedimientos de inserción, borrado y actualización utilizando esta configuración. Como siempre se aprende mejor de los ejemplo, a continuación ponemos el ejemplo trivial de mapeo, que nos va a permitir ver algunas cosas interesantes.

 

Como observará, con el método anterior podremos especificar los mapeos de los diferentes procedimientos, pudiendo personalizar desde el nombre de los mismos hasta el nombre de los parámetros, tanto de entrada como de salida. Bueno, hasta aquí esta pequeñita entrega, como rezaba el título era solamente un sneak… espero que los que conozcáis EF os animéis a hacer más clones y si encontráis mejoras no dudéis en contribuir…

 

Update 1: Parece que me he adelantado un pelin y la gente de ADO.NET ha liberado una especificación de esta característica mucho más completa, que complementa lo comentado aquí con tras de las estupendas características de esta nueva novedad como son:

 

  • Convenciones por defecto para los nombres de los SP. Es decir, si como anteriormente no especificamos alguna de las funciones, por defecto se buscarán los siguientes nombres de SP, type_Insert,type_Update y type_Delete. En nuestro caso Customer_Update, Customer_Insert y Customer_Delete.

 

  • Para las relaciones Many To Many hay soporte con SP para el trabajo de inserciones y borrados, revisar la especificación para más información.

Saludos

Unai

Cloud Tour

Ya estamos otra vez de gira, en esta ocasión hablando sobre la plataforma de cloud computing de Microsoft, Windows Azure. Aunque, desde un punto de vista especial y fuera de los convencionalismos típicos de esta plataforma. La idea es ver si Windows Azure también es una estupenda plataforma para aquellos que no trabajan en entornos Microsoft. La agenda y los detalles de las sesiones los podéis ver a continuación:

En mi caso, yo me encargaré de la plataforma de acceso a datos, dónde veremos las posibilidades que Windows Azure nos da. Espero que os guste, para los que no estéis registrados, aquí tenéis fechas y más información…. nos vemos..

AGENDA

  • 9:30 – 10:30 Introducción a la plataforma
  • 10:30 – 11:30 IaaS – Linux, máquinas y redes virtuales
  • 11:30 Café
  • 11:45 – 12:30 PaaS – Trabajando con Java y Eclipse
  • 12:30 – 13:30 PHP y Azure Web Sites
  • 13:30 Comida
  • 14:30 – 15:30 Almacenamiento en la nube: SQL, NoSQL
  • 15:30 – 16:30 Big Data y Apache Hadoop
  • 16:30 – 17:30 Desarrollo de backends para dispositivos móviles

Organización: Plain Concepts

Introducción a la plataforma

El objetivo de esta primera sesión será describir los principales servicios de la plataforma; Por qué puede interesar para mi empresa usar Cloud Computing, qué nivel de servicio, que opciones tengo si no trabajo con tecnologías Microsoft etc… Durante la sesión se hará especial hincapié en las diferentes opciones de interoperabilidad que existen y cómo es posible trabajar con otros lenguajes de programación como Java, Node.js o PHP e incluso desde otros sistema operativos, Linux y MAC.

IaaS – Linux, Máquinas y Redes Virtuales

La plataforma Windows Azure dispone de un servicio de infraestructura que permite de forma rápida y sencilla crear máquinas virtuales Windows y Linux. Durante esta sesión se mostrará las principales características de la misma y cómo es posible trabajar desde un ecosistema Linux, tanto a nivel de cliente como de servidor.

  • Cómo desplegar una máquina virtual Linux.
  • Cómo montar tu propia red virtual.
  • Cómo trabajar desde un ecosistema completamente Linux, tanto en desktop como en servidor.

PaaS, trabajando con Java y Eclipse

El servicio de “Plataforma como Servicio” es otro de los pilaras básicos de Windows Azure, el cual permite abstraernos de gran parte del trabajo de infraestructura y centrarnos únicamente en la aplicación que queremos desarrollar, posibilitando escenario de escalabilidad y disponibilidad difíciles de conseguir en otro tipo de soluciones. Durante esta sesión veremos de forma práctica cómo podemos desplegar aplicaciones Java con Eclipse en Windows Azure.

PHP y Azure Web Sites

Durante esta sesión se mostrará de forma prácticas las opciones disponibles para desplegar aplicaciones PHP en Windows Azure.

Durante esta sesión se empleará Windows Azure Web Sites para desplegar este tipo de aplicaciones, sirviendo a su vez para explicar con más detalle cómo es posible disponer de un escenario de integración continua con PHP, Azure Web Sites y GitHub.

Así mismo se verá cómo es posible trabajar de forma rápida y sencilla con WordPress, Drupal o Joomla.

Almacenamiento en la nube – SQL, NoSQL

Durante esta sesión se describirán las diferentes opciones de almacenamiento que están disponible en la nube, tanto base de datos relaciones, SQL Database y MySQL, como base de datos NOSQL como Windows Azure Table Storage, MongoDB o Cassandra.

De forma práctica podrá verse un ejemplo de cómo es posible trabajar con MongoDB, desplegado en una máquina virtual o haciendo uso de MongoDB como servicio.

Big Data y Hadoop

No se puede negar que Big Data y Hadoop son términos de moda en el mundo de IT, pero ¿sabes lo que realmente pueden aportar a tu organización? Y, aún más importante, ¿cómo podrías implementarlo dentro de tu ecosistema?

Durante esta sesión realizará una introducción a Big Data y Hadoop y de cómo es posible sacarle el máximo rendimiento a estas dos tecnologías dentro de nuestra organización.

Desarrollo de backends para el desarrollo de aplicaciones móviles

Aplicaciones para Android, Windows Phone, iPhone, iPad, Windows 8… casi todas tienen en común que generalmente necesitan de servicios de backend para ciertas funcionalidades; almacenamiento, notificaciones push, envíos de SMS, seguridad con diferentes proveedores de identidad etc… Durante esta sesión hablaremos de Mobile Services, una tecnología que permite disponer de forma rápida y sencilla de servicios de backend que pueden ser utilizados desde cualquiera de los dispositivos mencionando anteriormente, ya que además de ofrecer un API REST de uso dispone de SDKs propios de cada plataforma que simplifica su utilización.

 

Saludos

Unai

EF 6: Pluralization Service ahora es un servicio público

Esta ‘pequeña feature’ era algo que tenía en mente hacer desde hace tiempo, después de otros pull request con features y pequeños arreglos, he podido sacar un rato  y realizar la implementación del mismo como podéis ver en este change set.  La idea es básicamente poder tunear el servicio que se encarga de realizar la singularización y pluralización de nuestras entidades, por ejemplo para decidir por convención el nombre de una tabla. En realidad, este servicio es utilizado principalmente por PluralizingTableNameConvention y PluralizingEntitySetNameConvention para realizar su trabajo. Hasta ahora, es clase no era pública y su uso estaba fijado por las convenciones anteriores, no teniendo ninguna forma de cambiar la implementación del mismo. A lo largo de las siguientes líneas os contaré los cambios realizados y lo que podremos hacer en la siguiente versión de EF.

Haciendo el servicio público

Lo primero es crear  el contrato para este servicio, que como podéis ver a continuación es tan sencillo como lo siguiente:

 

Este servicio, por defecto, tendrá una implementación basada en lengua inglesa, llamado EnglishPluralizationService, que no es más que la adaptación a este contrato del servicio anterior, por compatibilidad. Para registrar la implementación que queramos usar se ha incluido un nuevo método en DbConfiguration llamado SetPluralizationService, gracias al cuál podremos establecer esta implementación, si es que queremos cambiar la existente. A continuación podemos ver un ejemplo de esto:

Un pequeño añadido aprovechando la coyuntura..

Ya metidos en faena, hay una pequeña cosa que podíamos hacer  para no obligar a nadie a crear un servicio de pluralización si alguna de las reglas del existente no le convenía o quisiera ‘customizar’ este trabajo. La idea es básicamente permitir al usuario incluir en el servicio de pluralización la definición de una entrada de diccionario, con los correspondientes Singular y Plural, como podemos ver en el siguiente fragmento.

 

Estas entradas de diccionario se pueden establecer en el constructor del servicio de pluralización antes de registrarlo, por ejemplo, ahora utilizando un IDbDependencyResolver, como vemos:

Bonus

Bien, una vez hecho público el servicio lo mejor era dar un ejemplo de implementación, por eso, otra de las cosas que he estado haciendo estas vacaciones ha sido la creación de este servicio de pluralización en castellano, aunque por ahora no lo he hecho público puesto que estoy mirando la mejor manera de hacerlo…en cuanto esté os comentaré como podréis utilizarlo….

 

Espero que os gustara la entrada y, como no, os invito a pasaros por el la página del proyecto en CodePlex y a contribuir de las muchas formas en las que se puede…

 

Saludos

Unai

EF 6: Buffering versus Streaming

Hace poco se incorporó un change set con un nuevo ‘breaking change’ dentro de la rama principal de Entity Framework. Este ‘breaking change’ se produce por el cambio en el modo de ejecución de las lecturas por parte de nuestras unidades de trabajo, pasando del modo habitual de lectura en streaming con un DbDataReader a un modo buffering, es decir, a la lectura temprana de los datos y al almacenamiento de los resultados en un buffer. A lo largo de esta entrada intentaremos ver  desde que supone para nosotros este cambio como desarrolladores, hasta las justificaciones para realizarlo, pasando como no, por algunas piezas de código que nos permitan entender mejor como lo han implementado.

El cambio

Cuando trabajamos con EF generalmente, solemos tener cosas como la siguiente:

 

Y todos tenemos claro que ese enumerador es una consulta diferida, técnicamente por un shaper, la diferencia de este trabajo en EF 6 con respecto a las anteriores estriba en como se hace la materialización de este enumerable. En la versión actual de EF tendremos un data reader que será usado en cada llamada al MoveNext del iterador. Aunque todos sabemos que internamente DataReader funciona con bloques para conjuntos de datos grandes estos se van incorporando a medida que se necesitan, es decir, hay un proceso de streaming de los datos del servidor a cliente. Para ver esto solamente tendríamos que realizar una lectura de un cojunto grande y ver como el BatchStarting y el BatchCompleted sucenden al comienzo de la lectura y cuando hemos iterado por todos los resultado, es decir, para la siguiente consulta, podríamos ver los siguientes valores en nuestro profiler

 

Comienzo de la lectura

Untitled1

 

final del bucle

Untitled2

 

Lógico según lo se sabemos sobre el comportamiento de nuestros data readers ¿ verdad ?. Bien, pues ahora intentamos hacer esto mismo con EF 6 y veremos lo siguiente nada más ejecutar el paso por el primero de los elementos…

 

image

 

La razón es la que comentamos más arriba, en la nueva versión de EF que tendremos el mecanismo de consultas reemplazará el DbDataReader por un BufferedDataReader (System.Data.Entity.Core.Objects.Internal.BufferedDataReader) el cual en realidad no es más que un envoltorio de un DataReader que hace todo la lectura de sus elementos en su inicialización y los almacena en una estructura interna BufferedDataRecord, de ahí el nombre de Buffered, que será usada por el materializador ( shaper ) para crear las distintas entidades.

Aunque esto pueda parecer un mero cambio interno a EF, en realidad no es tan sencillo y supone un breaking change porque tiene un impacto sobre las aplicaciones actuales. De entrada es lógico ver que hay una mayor presión de memoria, aunque sea memoria de generación 0, puesto que estamos duplicando los datos en el proceso de materialización. El segundo motivo es que por ejemplo si se rompe el bucle anterior por cualquier condición en la versión anterior no tendríamos porque haber traído todos los bloques del reader mientras que en EF 6 si habríamos traído todos los bloques del reader. Otro impacto posible lo podemos observar en la llamada a nuestro GetEnumerator, puesto que ahora necesitará más tiempo para completar el trabajo.

 

Los motivos

 

Las razones para movernos de un modo Streamed a Buffered se deben principalmente y tal como el equipo ha explicado en el siguiente design meeting a las siguientes razones:

 

  • Sql Azure connection resilience: Como todos sabéis, el trabajo con Sql Azure tiene una problemática especial que nos obliga a necesitar en ciertos escenarios de reintentos en nuestro trabajo con EF, Cesar de la Torre escribió hace ya mucho tiempo sobre esto. Dentro de la iniciativa del equipo por hacer más robusto el uso de EF con Sql Azure este cambio es necesario ya que no retarda el uso de una conexión más allá de lo necesario.
  • El tiempo de uso de una conexión se reduce potencialmente
  • Ya no es necesario MARS  ( obligatorio con lazy loading en la versión actual )

Y si quiero mi antiguo comportamiento

Bien sea por compatibilidad o porque el escenario así lo requiera, en EF tendremos un mecanismo para seguir usando streaming en nuestras consultas, para ello, solamente tendremos que utilizar el método AsStreaming, gracias al cual EF volverá a usar un DbDataReader en lugar del ya mencionado BufferedDataReader. A continuación podemos ver un ejemplo de ello:

 

 

Bueno, hasta aquí hemos llegado, espero que todos tengamos en cuenta este cambio si decidimos migrar aplicaciones de EF 5 a EF 6 puesto que tal y como hemos dicho puede tener impacto y producirse situaciones no deseadas sino nos fijamos…

 

Saludos

Unai

EF 6: Estableciendo las configuraciones de forma automática

La verdad es que no hace muchos días que publiqué un post con este trabajo para todos aquellos, que como yo, consideraran interesante el hecho de disponer de una forma automática de agregar las configuración de nuestro modelo, con el fin de facilitar el trabajo y prevenir ese código repetitivo que solemos ver muy a menudo. Para que no tengamos que recurrir a lo mismo en EF 6, me decidí por hacer un pequeño pull request que pudiera contener esta funcionalidad, ahora, que como ya sabréis todos, Entity Framework es Open Source  y, por lo tanto, abierto a que la comunidad pueda contribuir. Los que hayáis pasado alguna vez por el portal del proyecto en Codeplex sabréis que hay multitud de información sobre las diferentes vías de contribución, que no tienen porque ser solamente código, y como hacer estas contribuciones de una forma ordenada y consensuada. La palabra consensuada es importante aquí puesto que por mucho que a nosotros nos parezca importante y válida una contribución esta no tiene por que tener la misma validez para el equipo, por ejemplo, porque la pieza o piezas en las que vayamos a tocar se vayan a rediseñar o, a otra multitud de factores que se nos puedan escapar. El principio Don’t Push Your Pull Request es la norma a seguir dentro del equipo de desarrollo y por lo tanto el primer trabajo que tenemos que hacer es discutir con ellos lo que queremos hacer y por supuesto como lo vamos a hacer, en este caso, la sugerencia de pull request y su discusión la podéis ver aquí.

Bueno, después de ver el feedback y de las guías sobre como les gustaría la aportación, el resultado que ha quedado es este Change Set con la característica comentada anteriormente y, que pasaremos a desgranar ahora mismo.

 

Carga automática de configuraciones

 

Bien, esto es lo más básico y a la vez lo más natural de esta característica, puesto que como ya comentamos su primer trabajo es hacer la carga de configuraciones de forma automática, eliminando las típicas líneas repetitivas de carga de configuraciones, que en un proyecto real serán muchas y por lo tanto con un impacto en legibilidad y mantenibilidad. Es decir, lo que nos permitiría es cambiar cosas como esta:

 

Por lo siguiente:

Visibilidad de tipos y constructores

 

Para realizar esta carga automática de configuraciones no estamos restringidos a ninguna visibilidad de nuestras clases, ni de sus constructores. De hecho, esto es lo ideal, puesto que estas clases solamente tienen fines de configuración y no están pensadas para ser usadas más que por la infraestructura, parece lógico que pudiéramos escribirlas como por ejemplo en la siguiente de forma no pública y con un constructor privado.

 

 

Configuraciones en jerarquía

 

La última de las características de este trabajo, es el soporte a jerarquías de configuraciones, es decir, que nuestros tipos de configuración no implementen de forma directa EntityTypeConfiguration<>. Un ejemplo de este tipo de escenarios podría ser algo como lo siguiente:

 

Si observa, lo que hemos hecho, con meros fines de ejemplo, es hacer una pequeña base para nuestras configuraciones que nos agrega un prefijo tbl a los nombres de nuestras tablas. Esta configuración base la podríamos utilizar en todas aquellas entidades que nos interesaran que ya tuvieran OOB esta característica.

 

Pues bien, como hemos dicho, aún en estas situaciones nuestro AddFromAssembly seguirá funcionando perfectamente y cargando nuestras configuraciones de la forma correcta, excluyendo tipos abstractos y definiciones de tipos genéricos…

 

Bueno, espero que os resulte interesante esta novedad que tendremos en EF 6 y espero, que esta contribución os sea de la mayor utilidad posible, con ese fin está hecha…

 

saludos

Unai

Recursos, mensajes de excepción y otras cadenas…..

Bueno, imagino que después de leer el título le quedará bastante claro de lo que vamos a hablar en este pequeño post. A lo largo de este tiempo he visto muchas y diversas formas de manejar los típicos mensajes de excepción y otros elementos localizables de nuestro código ( sin hablar nada de UI en este caso ), unas mejores y otras peores. Con la llegada de .NET y los recursos incrustados, muchos de los inconvenientes tradicionales que teníamos se vieron resueltos. Elementos como el fallback en la resolución de la cultura, los conceptos de culturas específicas y neutras, sin duda, facilitaron enormemente nuestro trabajo. El consumo de estos recursos incrustados de .NET, por regla general, se realiza utilizando las propiedades de la clase que se nos genera automáticamente por cada uno los archivos de recursos [ recuerde que por defecto estos ficheros tienen asociada una custom tool, ResXFileCodeGenerator, para la generación de esta clase ]. Elementos habituales podrían ser, algunos como los siguientes:

 

 

 

Alguno de los problemas con esta forma de trabajo surge por ejemplo cuando queremos hacer estos mensajes parametrizados, puesto que tendríamos que recurrir a cosas como la siguiente:

 

Cuando se utiliza esta entrada de recursos, no hay más remedio que acudir a nuestro mensaje para descubrir si este toma parámetros o no y establecerlos en caso necesario, por no hablar de que la legibilidad podría verse afectada, sin duda. Mecanismos para intentar solventar estos problemas hay muchos y variados pero uno que últimamente me ha gustado y que he seguido ha sido el utilizado por el equipo de EF para hacer la gestión de esta problemática. Mecanismo que se basa en una sencilla plantilla .tt  junto a un fichero de recursos que nos permite generar 2 clases fundamentales Strings y Error preparadas para ser utilizadas en el código de una forma más simple y legible que mediante el código por defecto de ResXFileCodeGenerator. De entre algunas de las características que incorpora esta plantilla podemos ver que expone en forma de parámetros los parámetros de las entradas del archivo de recursos, de tal forma que si, por ejemplo, tenemos una entrada con valor “any message for {0} and {1}”  esta plantilla nos expondrá en nuestra clase Strings un método similar a lo siguiente:

 

 

Con lo cual, el uso anterior de esta clave de recurso podría realizarse como, por ejemplo de la siguiente manera:

 

 

La parte de Error, es quizás, más interesante todavía, puesto que nos permite generar a partir de los claves de nuestros ficheros de recurso métodos que devuelvan las excepciónes que necesitemos, cuyos tipos se extraen además del mismo archivo de recursos gracias a un pequeño trick con el campo comentarios, puesto que interpretan comentarios como ## ExceptionType=InvalidOperationException como la necesidad de generar un método que devuelva una excepción InvalidOperationException con el mensaje de la misma entrada del recurso. A continuación podemos ver un ejemplo de uno de los mensajes de Error que tenemos en el código de EF

 

 

 

Bueno, amigo lector, le invito desde aquí a revisar como otros resuelven problemas habituales en nuestro trabajo. En este caso, esta plantilla de la que acabamos de ver es un ejemplo bastante simple de tratar el problema. Aunque hay que tocar un par de cosas para que la misma se pueda utilizar en cualquier proyecto la verdad es que es terriblemente sencilla, por lo que le invito a probarla…

 

Saludos

Unai

EF Agregando configuraciones de forma automática

Hay ciertas situaciones en las que las convenciones de EF para nuestros mapeos de entidades no nos sirven o bien no nos sirven completamente, un ejemplo de esto es cuando trabajamos con una base de datos existente, dónde, seguramente, la convención del nombre de las tablas ( pluralización en inglés de los nombres de las entidades ) no nos sirva, y así con otras muchas convenciones. En estas situaciones, es más que seguro que tengamos que hacer uso de las configuraciones personalizadas, instancias de EntityTypeConfiguration<> y ComplexTypeConfiguration<>En estos casos, cuando el modelo es grande, el aspecto que tendrá nuestro OnModelCreating será un poco esperpéntico, algo similar a lo siguiente:

 

 

El problema de este tipo de códigos, amén del matenimiento, es la poca legibilidad del mismo, donde por ejemplo, nos costaría encontrar si una entidad está o no mapeada. Solventar este problema y hacer un código más legible y facilitar la vida al desarrollador no es difícil,  ya que en realidad lo único que estamos haciendo ahí es configurar todas las clases de un determinado tipo, algo por lo tanto muy fácil de automatizar. En el siguiente repositorio de GitHub he implementado una posible solución para estos problemas, que nos permite cambiar este código anterior por algo como lo siguiente:

 

o, si tenemos los mapas de configuración en otro ensamblado, podríamos hacer:

 

Espero que os guste y, sobre todo, que os sea de utilidad…

EF 6 Alpha: Custom Conventions

El tema de las convenciones personalizadas para el modelo de Code First sin duda ha sido una de las cosas que más echamos de menos en EF, de hecho, durante alguna de las betas estas posibilidades estaban incluidas como en su día vimos en algún post. De entre las distintas novedades de esta versión preliminar de EF 6 podemos destacar la vuelta al ruedo de estas features, aunque ahora con una implementación, en mi opinión, mucho más acertada. A lo largo de la siguiente entrada intentaremos darle un vistazo a estas nuevas posibilidades, si lo desea, también puede leer el walkthough que el equipo de ADO.NET tiene sobre este tema.

Introducción

 

Todas las convenciones de EF, están basadas en la siguiente interface, IConfigurationConvention:

Esta interface, como observará tiene dos parámetros genéricos TMemberInfo y TConfiguration, que nos permite establecer, por un lado con TMemberInfo si la configuración es para un tipo o para una propiedad y en ultimo lugar a que elemento en concreto se aplica, para el caso de las propiedades ConfigurationBase tiene un jerarquía similar a esta:

 

ConfigurationBase

  -> Property Configuration

->NavigationPropertyConfiguration

->PrimitivePropertyConfiguraiton

    -> BinaryPropertyConfiguraiton

    -> DateTimePropertyConfiguration

     -> ….

Dicho esto, para crear por ejemplo una convención que afecte a propiedades de tipo DateTime tendríamos que implementar una clase como la siguiente:

Por supuesto, dentro del método Apply tendríamos que establecer que queremos en la convención, si se fija, el delegado configuration nos permite obtener la configuración actual de esa propiedad, con lo cual, podríamos ver/modificar la misma. En este caso optaremos por hacer lo mismo que el el walkthoug, puesto que me parece muy ‘real’ el hecho de adaptar el tipo de datos en Sql Server a datetime2 para estas propiedades.

 

Por supuesto, usted puede revisar el miembro memberInfo para decidir a que propiedades se aplica, por ejemplo, le podría interesar solo aplicar esta convención a las propiedades cuyo nombre por ejemplo acaben con un postfijo determinado, aunque esto, en mi humilde opinión no es algo que me guste para nada. Las convenciones a nivel de entidad, son prácticamente iguales, con la salvedad de que lógicamente configuran aspectos de la entidad y no de las propiedades, por ejemplo, la convención de que la propiedad Id sea la clave primaria de una entidad podría haberse escrito así.

 

Bien, una vez que tenemos definidas nuestras convenciones, para agregarla usaremos la propiedad Conventions, que ya es conocida de nuestros DbContext, con la diferencia que ahora dispone de métodos para incluir convenciones y no solamente para eliminarlas. De hecho, incluso me permite establecer el orden de ejecución de las mismas.

 

 

Con el fin de simplificarnos la vida, el equipo de ADO.NET nos ha creado una pequeña clase LightweigtConvention con la cual podremos establecer convenciones sin necesidad de escribir una nueva clase para las mismas. Esta clase no es más que una implementación de IConventionConfiguration para tipos y propiedades que hace uso de una clase, EntityConventionConfiguration para agregar convenciones mediante un API fluent.

Utilizando esta clase, por lo tanto, podríamos crear una convención tal y como sigue:

 

Puede observar como el trabajo a realizar depende de si configura propiedad o entidad y este está representado por las clases LightweighPropertyConfiguration o LightweighEntityConfiguration.

 

Bien, pero ¿y si quiero hacer las convenciones con atributos? Pues sencillo, en vez de implementar IConfigurationConvention trabajaremos con AttributeConfigurationConvention, el cual, nos permite indicar que atributo es el que será el atributo marcador, es decir aquel atributo que EF revisará para saber que tiene que aplicar una convención. Para verlo, utilizaremos también el del walkthoug, puesto que al igual que con el DateTime es también bastante habitual. En este ejemplo el objetivo es poder disponer de un atributo, por ejemplo NonUnicodeAttribute que nos permita decorar a las propiedades como no unicode. Pues bien, este atributo será un atributo marcador, es decir, no necesita código de trabajo con EF, por ejemplo igual que así:

 

Bien, ahora que tenemos creado el atributo marcador, solamente tenemos que aplicarle la convención ,tal cual podríamos hacer antes con nuestras PrimitivePropertyConfiguration…

 

Sencillo ¿verdad?…Bueno, espero poder publicar alguna entrada más sobre EF 6, de hecho hay un par de novedades que me parecen super interesantes.. y me gustaría también sacar algo de tiempo para colaborar un poco con el código, a ver si lo logro…

 

Saludos

Unai