EF Migrations, EF 4.3 y que nos deparará el futuro

Hoy mismo se ha hecho pública la primera beta del paquete de “migraciones” que el equipo de Entity Framework ha estado preparando durante ya hace algún tiempo, de hecho, en este mismo blog ya hemos publicado unas cuantras entradas,aquí y aquí, referidas a su funcionamiento. Lo más destacable de este anuncio, a mayores de los cambios y novedades en el paquete, comentaremos sobre esto más adelante, es el hecho de que incorporarán Migrations como parte de EF 4.3, es decir, que ya no existirá el paquete EntityFramework.Migrations como tal. Desde mi punto de vista, esto es sin duda una gran idea, puesto que el trabajo con migraciones no es “algo opcional” en un proyecto real.  Hablando con un miembro del equipo sobre cuales serían las implicaciones directas de este paso se puso sobre la mesa la posibilidad de que alguna funcionalidad estuviera duplicada entre el code base de EF Code First y el paquete de migraciones. Un ejemplo de esto, podría ser por ejemplo los inicializadores de EF, IDatabaseInitializer<T> cuya funcionalidad podría solaparse con el Seed que podemos hacer en nuestro DbMigrationsConfiguration, aunque en mi opinión ambos podrian tener propósitos diferentes. Lo más interesante de este movimiento, es lo que se puede leer por detrás, es decir, como poco a poco el equipo de EF está haciendo movimientos para apartarse de la dependencia de .NET Framework, dependencia que seguro que afecta enormemente a su ciclo de vida, a su capacidad de entrega y a la resolución de problema de una forma más agil. Seguro, que no dentro de mucho, nos darán alguna sorpresa en cuanto al ciclo de vida y modelo de desarrollo con respecto a EF.

 

Bueno, al chollo:

Realmente, el funcionamiento de esta beta es bastantet similar, de hecho ya advierte de que hay unas pequeñas features y sobre todo refactoring. Lo primero en lo que nos podemos fijar con respecto a las versiones anteriores es que ahora la clase DbMigrationContext de las versiones anteriores se sustituye por DbMigrationsConfiguration:

 

Por supuesto, aunque ahora no se muestren, esta clase nos sigue ofreciendo la posibilidad de establecer las generadores de código SQL y codigo C# de las migraciones que hagamos, además de otra serie de flags, como por ejemplo AutomaticMigrationDataLossAlowed, que nos permitirán modificar algún comportamiento adicional. Otro elemento a mayores, es ver como han creado un nuevo método extensor, AddOrUpdate que nos simplificará el Seed de los datos.

Al igual que hacíamos antes, también podemos hacer customizaciones en las distintas migraciones, así, por ejemplo, si nos interesará poder un índice sobre la columna FirstName de nuestra tabla authors podríamos hacer alog como lo siguiente: 

A mayores de los métodos de customización de DbMigration, base para todas las definiciones de migración, esta nos ofrece un método llamado Sql que nos servirá para ejecutar, en el caso de necesitarlo, un comando SQL, como por ejemplo un  UPDATE para poner un valor por defecto a una de las nuevas columnas, etc.

Bueno, aquí se queda esto por ahora… Para los que os guste el tema y aún no hayais podido profundizar os recomienod los recomiendo las guias paso a paso del equipo de Entity Framework que están aquí y aquí.

 

Nos despedimos hasta la próxima dónde empezaremos una serie sobre RavenDB.

 

Un saludo

Unai

HOT:Inserciones masivas en Sql Sersver vs Mongo DB ( III)

 
DESCARGO DE RESPONSABILIDAD

Antes de empezar la entrada me gustaría dejar claro que esto es un pasatiempos, una forma de dilucidar quien pagaba las cenas durante el tiempo que nos toco a los dos estar perdidos en una ciudad que no es la nuestra con nuestros respectivos trabajos. La idea de esta serie de blogs no es ver si queremos más a Papa o a Mama, a Sql Server o a una NoSQL. Los resultados que se obtengan no tienen porque hacer pensar que una es mejor que la otra ( sobre todo cuando son compatibles) y por supuesto el performance no es una(la única) razón de selección de una NoSQL como Mongo, escalabilidad, schema-free, base, last-update ni de un sistema transacciónl como Sql Serve. Si esto te queda claro y quieres jugar con nosotros, y por supuesto, aprender como lo hemos hecho nosotros, a forzar situaciones como la presente tanto de Sql Server como de Mongo entonces sigue leyendo…

 

La bala de la recamara….

 

Me voy a permitir adelantarme al post de Pablo Doval con sus conclusiones puesto que, este finde esta muy, pero que muy ocupado haciendo que el Sql Server de otro ande más rapido. Como había dicho, me preocupaba mucho el tema de mis bloqueos, puesto que o cambiaba de tercio o no tendría mucho margen de mejora. Pensando y pensando (algún comodín también) me puse a ver que podría hacer y recorde que con las Capped Collections de Mongo DB podría ganar algo, puesto que a la hora de crearlas podría especificar el espacio a ocupar y por lo tanto hacer un pequeño prefetch de la base de datos. En realidad, una colección capped no es más que una colección con un tamaño máximo dado y un número de documentos máximo. La definición exacta de las capped collections la tenéis en la siguiente frase:

 

Capped collections are fixed sized collections that have a very high performance auto-FIFO age-out feature (age out is based on insertion order). They are a bit like the "RRD" concept if you are familiar with thatç

Bueno, “high performance auto-FIFO”…. esto es lo que andaba buscando…. Vamos, además, a unirlo con un poco de paralelismo para ver si nos sorprendemos con los resultados que obtengamos. Para ello, lo primero que haremos será levantar nuestro servidor de mongodb con prácticamente las mismas opciones que en la entrada anterior, he incluido alguna más pero no han tenido demasiado efecto…

 

mongod  — dbpath c:mongodata

        — nohttpinterface

        — noauth

        — nojournal

        — quiet

        — verbose

        — diaglog

        — logpath log.txt

        — install

Ahora, modificaremos nuestro código para que se cree la colección a utilizar como una capped collection, fíjese que en esta creación hemos puesto ya tamaños máximos de documentos y espacio. Además también hemos realizado otra optimización al poner SetAutoIndex a false eliminando así la creación del índice  sobre _id por defecto.

 

El paralelismo es sencillo, basta con usar el magnífico API de TPL y agregar unas cuantas Task como se ve a continuación. Como seguramente muchos os preguntéis, he probado diferente número de hilos, y la verdad es que no he obtenido mejor, lo cual, me hace indicar que el problema no es de contención en el procesador, ni de uso, es ya un tema en MongoDB.

 

El código de Work es el siguiente  :

 

Venga, vamos a hacer la prueba…. [redoble de tambores…….] el resultado es …. 1,6 segundos, gracias a las capped collections y al prefetch del tamaño  y número de documentos he aumentado el rendimiento enormemente, de 3,5 a 1,6 segundos en insertar 500K documentos…

…….Sigo preocupado…..

 

Las malas lenguas me han dicho que pablo bajará ese tiempo…. y ya, lo único que se me ocurre es montar un sharding y no tengo muy claro que eso NO sea hacer TRAMPAS….

Nos leemos,

Unai

HOT:Inserciones Masivas en MongoDB vs Sql Server (II)

DESCARGO DE RESPONSABILIDAD

Antes de empezar la entrada me gustaría dejar claro que esto es un pasatiempos, una forma de dilucidar quien pagaba las cenas durante el tiempo que nos toco a los dos estar perdidos en una ciudad que no es la nuestra con nuestros respectivos trabajos. La idea de esta serie de blogs no es ver si queremos más a Papa o a Mama, a Sql Server o a una NoSQL. Los resultados que se obtengan no tienen porque hacer pensar que una es mejor que la otra ( sobre todo cuando son compatibles) y por supuesto el performance no es una(la única) razón de selección de una NoSQL como Mongo, escalabilidad, schema-free, base, last-update ni de un sistema transacciónl como Sql Serve. Si esto te queda claro y quieres jugar con nosotros, y por supuesto, aprender como lo hemos hecho nosotros, a forzar situaciones como la presente tanto de Sql Server como de Mongo entonces sigue leyendo…

Bueno, seguro que muchos habéis leido la entrarada de mi compañero de batallas y amigo Pablo Doval sobre un pequeño pique “paga cenas” a ver quien insertaba de una forma más rápida 500 K de registros. En la primera entrada de mi contrincante hemos podido ver como su primer esfuerzo ha resultado en 4 segundos escasos, quiero imaginarme que con escasos no se refiere a 0,9 por lo que entenderé que mi primer reto es superar simplemente 4 segundos. Bien, 4 segundos, no está nada mal, sobre todo porque teniendo en cuenta lo que ha utilizado me temo que tiene un gran arco de mejora ( aunque no seré yo quien se lo diga, más que nada porque de Sql Server el ya sabe mejor que yo …). Vamos a ver que podemos hacer con nuestro jueguete, por supuesto, no empezaremos haciendo ninguna optimización, lo más simple, así tendremos una ligera idea de por dónde andamos.

 

El primer intento

 

Tal y como acabo de comentar el primer intento será lo mas simple posible, insertaremos en MongoDB 500K documentos. Si, documentos, para los que no lo sepais, MongoDb es una base de datos documental, entendiendo como esto a algo similar a lo que podéis ver en la imagen de la derecha. Las normas de nuestra pequeña apuestas decían que teníamos que inUntitledsertar 500K documentos ( el filas ) con un tipo de datos Guid y una cadena con 20 caracteres. Por lo tanto, abriremos un proyecto de Visual Studio 2010 y vamos a empezar a jugar. Lo primero será agregar las librerías necesarias para trabajar con Mongo DB, para ello podemis ir hacia la sección de drivers de Mongo DB y descargar los de C# o mejor aún utilizar el paquete de NuGet que esta gente tiene disponible, concretamente el paquete se llama mongocsharpdriver.

 

Levantando el servidor

 

Lógicamente, antes de conectarnos tenemos que levantar un servidor de MongoDB, para ello, por ahora, no utilizaremos ninguna setting especial, de hecho, lo levantaremos como una consola y no como un servicio de Windows ( si, ya se que eso puede tener un impacto, veremos si es cierto… ). Es decir, levantaremos el servidor con las simples instrucciones siguientes:

 

mongod.exe –dbpath c:mongodata [c:mongodata es el path para alojar la base de datos]

Ahora, es hora del código, con las siguientes lineas voy a acceder a una colección llamada tests en una base de datos llamada apuesta dónde posteriormente intentaré introducir los 500 K registros.

 

Ahora, solamente me queda darle a mi bucle y esperar los resultados para ver desde dónde vamos a empezar a jugar, espero sinceramente que no sea muy alto porque 4 segundos es un muy buen número. Mientras me preparaba para hacerlo me puse a pensar si lo haríamos de forma tipada o no. Es decir, el API de MongoDB me permite definir los distintos documentos mediante clases que posteriormente el serializará al formato de trabajo. Aunque no quería hacer ninguna optimización temprana me parecía que esto sería un poco estúpido y por lo tanto trabajaría directamente con documentos no tipados, es decir, con BsonDocuments.

 

……………………. ( redoble de tambores)… 18,74 segundazos…… bufff, más de 4 veces que el mejor número de Pablo. Lo primero que hago es comprobar que no he comentido un error, que todos los datos estan en la base de datos, por lo que me conecto a mongo y hago una revisión del numero de documentos y del formato que contienen, en la siguiente imagen podéis ver los pasos que he seguido desde la shell de MongoDb para hacerlo.

 

Untitled2

 

 

….. unos ínfimos cambios y otro disparo….

 

Bien, estamos lejos, pero la verdad, teniendo en cuenta como lo hicimos, tampoco es que me asustará demasiado, hay dos cosas que podemos arreglar rápidamente, la primera es que cuando levantamos el servidor de Mongo como consola no desabilitamos el stdout ni el nivel de verbosidad, por lo tanto, segurmanente eso esté influyendo bastante.  La segunda es que mongo dispone de un sistema de batching por el cual podemos insertar un conjunto de documentos de forma simultanea.

 

Empezaremos los cambios por levantar una instancia del servidor de mongo como un servicio de windows con la siguiente parametrización:

 

mongod –-install [lo instalamos como un servicio]

       –diaglog 0 [deshabilitamos los diagnostics log]

       –quiet [reducimos la verbosidad de standard out

       –nojournal [ eliminamos la feature introducida en 1.8 para asegurar recuperación de datos no insertados en caso de crash]

Ahora, le toca la parte al código,  vamos a hacer el batching, para ello, modificamos nuestro código de inserción por el siguiente:

 

Ahora tomamos el tiempo y es ….5.005 segundos…. nada mal, si señor, estamos cerca ya de nuestro amigo…. pero aún falta ganar un segundo por algun lado. La primera parece pensar en jugar con los tamaños del batch pero después de algunas pruebas la mejora no es substancial como para ponerla, en mi máquina mi mejor respuesta es con un tamaño de 600  y a partir de 1500 los tiempos se hacen muy grandes. Por lo que parece que se mueve mejor con batch pequeños de estos documentos que muy grandes…

 

 

…tercer disparo y Pablo paga la cena (hoy)

 

Hay que ganar un segundo, ese es el reto ahora. Como lo hacemos?? bueno, a ver, vamos a revisar las opciones de inserción para ver si podemos tunear algun parámetro. Si, nos fijamos en las sobrecargas de InsertBatch, veremos que podemos incluir unas opciones de insercion por medio de la clase MongoInsertOptions. Si revisais esta clase, veréis  que hay tres parámetros importantes, CheckElementNames,SafeMode y Flags. El primero, nos permite decidir si queremos comprobar los nombres de los documentos, claves, collecciones etc antes de procesar un insert, el segundo permite especificarnos el modo de seguridad por defecto y el tercero el comportamiento en caso de fallo. Vamos a tunear estas opciones con nuestros batch y a ver que resultado tenemos….

 

…youhuuuuu 3.50 segundos… Pabloooooooooooooooooooooooooooooooo pagas la cena!!!!!!!!!!!!!!!!!

 

 

…aún así, sigo preocupado

 

Si, sigo preocupado porque Pablo tiene buenas posibilidades de mejora y yo, viendo las estadisticas de mi Mongo, siguiente imagen, veo que si quiero bajar de esos tiempos tengo que cambiar algún concepto y usar algo más de artillería… pero no se si me llegará…. en fin, ya veremos si supera los 3.50 y por cuanto lo supera…

 

Untitled3

 

Nos veremos en la siguiente…

Unai

DDD-CQRS post event

Bueno, tras una semana dura el evento de IASA sobre DDD y CQRS que he tenido la suerte de co-organizar junto a Cesar de la torre y el resto de miembros fundadores de IASA, llega el momento de hacer un pequeño recopilatorio. La verdad, pensar al principio en tener a Eric Evans, Udi Dahan y Diego Vega ( EF Team ) en un evento gratuito abierto a todas las tecnologías era algo que nos parecía muy, pero muy complicado, por momentos imposible. Al final, gracias a los distintos patrocinadores el evento se pudo producir y disfrutamos de magníficas sesiones, por supuesto incluyo aquí al resto de participantes ( alfredo casado, jorge serrano etc..  y un servidor :-)).

Además de todas estas charlas gratuitas, también teníamos dos dias de trabajo completos con Eric Evas y Udi Dahan, unos cursos por un precio más que razonable, yo diría que casi hasta regalado, que han tenido un gran aceptación y practicamente llenarons las plazas disponibles. Se, por mi propia experiencia y porque he podido hablar y conocer a muchos de los asistentes, que los cursos han sido muy bien aceptados y que todos repetiríamos….

Os dejo una pequeña foto con Eric Evans, Udi Dahan, Diego Vega, Pierre, Javier Calvarro y Cesar de la Torre y un servidor

 

DSC_0034

Espero que esto lo podamos volver a repetir en IASA Spain.

 

Unai