domingo, 30 de marzo de 2014

Presentación Sql Azure y Entity Framework

Hola amigos, les comparto la presentación de mi charla dictada en el Global Windows Azure BootCamp Medellín en la cual estuve compartiendo sobre Sql Azure y Entity Framework, espero sea de su interés.


[EntityFramework] Resumen Code First

Hola amigos, les comparto el resumen de todo lo que aprendimos en esta serie de artículos acerca de Entity Framework Code First, espero les sea de utilidad:

Enfoques en Entity Framework

  • Conocimos los tres enfoques que tenemos en Entity Framework, DataBase first, Model first y code first, y tuvimos un punto de referencia para elegir uno de ellos.

  • Aprendimos conceptos básicos y a tener en cuenta sobre Entity Framework Code First.

  • Aprendimos a crear nuestro modelo conceptual a través de clases POCO y luego vimos cómo crear nuestra base de datos basados en nuestras clases.

  • Aprendimos a configurar nuestras entidades para definir ciertas características de base de datos a través de atributos o Data Anottations.

  • Aprendimos a configurar nuestras entidades para definir ciertas características de base de datos a través de Fluent Api.

  • Aprendimos a configurar una relación de uno a uno entre nuestras entidades.

  • Aprendimos a configurar una relación de uno a muchos entre nuestras entidades.

  • Aprendimos a configurar una relación de muchos a muchos entre nuestras entidades.
  • Aprendimos a usar migraciones para actualizar los cambios de nuestro modelo a nuestra base de datos, además aprendimos a inicializar nuestra base de datos con datos de configuración.
  • Aprendimos a usar la herramienta de Power Tools para Entity Framework en Visual Studio, en especial para Code First.
Saludos y buena suerte!

viernes, 28 de marzo de 2014

[EntityFramework] Power Tools

Hola amigos, para terminar con esta serie de post acerca de Entity Framework Code First les quiero compartir una herramienta llamada Entity Framework Power Tools, que no es más que una extensión para visual estudio, la cual pueden encontrar en el siguiente sitio:

Entity Framework Power Tools

O también la pueden descargar a través del administrador de extensiones de su Visual Studio. Esta es una extensión bastante útil a la hora de elegir trabajar con Code first. Por ejemplo puede ser bastante engorroso crear por primera vez nuestra base de datos basado en nuestras entidades, ya que nos podemos equivocar en muchas cosas y se nos pueden pasar muchos detalles, pues bueno a través de este power tool podemos ver cómo va a quedar nuestro modelo antes de generar la base de datos para validarlo.

Adicional otra característica que en mi opinión es bastante útil es la herramienta de ingeniería inversa, que nos permite generar las clases POCO para una base de datos ya existente, esto para las personas que prefieran solo trabajar con Code First y no con otro enfoque de Entity Framework, en caso tal que tengan ya creada su base de datos podrán generar las entidades a partir de esta.

Adicional esta herramienta tiene otras características, las cuales pueden observar en el link que mencioné anteriormente, en mi opinión las dos características mencionadas son las más útiles.

Bueno amigos eso es todo, espero les sea de utilidad esta herramienta en sus proyectos, con esto damos por terminado nuestro tutotial acerca Entity Framework code First.

Saludos y buena suerte!

martes, 18 de marzo de 2014

[EntityFramework] Usando migraciones para actualizar cambios en nuestro modelo en Code First

En esta serie de artículos sobre Entity Framework Code First hemos visto diversos temas, desde creación y configuración inicial, hasta trabajo con las entidades. Y ahora que vamos en este punto surge la necesidad y la interrogante, de cómo podemos actualizar nuestra base de datos cuando surgen cambios en nuestras entidades. Pues bueno en este post vamos a ver cómo lo podemos hacer.

En primera instancia quiero mencionar que hay varios tipos de inicialización de base de datos en Entity Framework Code First, los cuales explico a continuación:

CreateDatabaseIfNotExists: Es el tipo de inicialización establecido por defecto, y solo crea la base de datos si esta no existe, es decir la primer vez que ejecutemos la inicialización a no ser que eliminemos la base de datos y volvamos a ejecutar, hay que tener en cuenta que si trabajamos con esta inicialización y cambiamos nuestro modelo obtendremos un error.

DropCreateDatabaseIfModelChanges:  Este tipo de inicialización elimina la base de datos existente y la crea de nuevo con las actualizaciones, siempre y cuando existan cambios en nuestro modelo de clases, la desventaja con esto es que tendremos perdida de datos.

DropCreateDatabaseAlways: Este tipo de inicialización elimina la base de datos existente y la crea de nuevo sin importar si hay nuevos cambios en el modelo o no. esto siempre conllevara perdida de datos y problemas de rendimiento al siempre tener que crear la base de datos.

Custom DB Initializer: Adicional podemos crear nuestro propio inicializador de base de datos si necesitamos algo muy específico, otro tipo de configuraciones, o ejecutar otro proceso externo para la inicialización, para esto podemos crear una clase que herede de una clase de inicialización cómo por ejemplo MigrateDatabaseToLatestVersion u otro de los mencionados.

MigrateDatabaseToLatestVersion: Nos permite actualizar automáticamente la base de datos, una vez inicie la aplicación, las actualizaciones pendientes se reflejaran en nuestra base de datos, este tipo de inicialización nos permite conservar los datos obviamente si no se trata de una instrucción Drop o Delete por ejemplo. Con este tipo es que podremos implementar migraciones en nuestra aplicación, por esto es importante conocer los diferentes tipos de inicialización que nos ofrece Entity Framework Code Fist.

Ahora sí, vamos a ver cómo implementar migraciones en nuestra base de datos.

Lo primero que debemos hacer es habilitar las migraciones, esto lo podemos hacer a través de la consola de paquetes nuget, de la siguiente forma:

En la barra de menús de Visual Studio seleccionamos Herramientas / Administrador de paquetes / Consola de administrador de paquetes y en esta consola seleccionamos en proyecto por defecto nuestro proyecto de acceso a datos donde tenemos nuestro modelo y escribimos lo siguiente:

enable-migrations -EnableAutomaticMigrations:$true

De esta forma se habilitan las migraciones en nuestro proyecto nos damos cuenta si leemos todo el log que se genera en la consola, ahora vamos a configurar nuestro contexto para sopórtalas.

Ahora si vamos al explorador de soluciones, veremos que se ha creado una carpeta llamada Migrations la cual contiene una clase llamada Configuration.cs.

Si exploramos la clase Configuration veremos que en su constructor el atributo AutomaticMigrationsEnabled se encuentra establecido en true, tal cual se lo indicamos en la consola de Nuget al ejecutar el comando, adicional veremos que hay un método sobre escrito llamado Seed, el cual nos permite cargar datos iniciales en nuestra base de datos, por ejemplo para cargar datos de configuración que se requieran desde el inicio para su correcto funcionamiento o para cargar tablas maestras de nuestra base de datos.

    internal sealed class Configuration : DbMigrationsConfiguration<EF6CodeFirst.Dominio.Context>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
            AutomaticMigrationDataLossAllowed = true;
        }
 
        protected override void Seed(EF6CodeFirst.Dominio.Context context)
        {
            context.Productos.AddOrUpdate(
                p => p.Codigo,
                new Producto { Codigo = 1, Nombre = "Leche1", Descripcion = "Producto Lacteo" },
                 new Producto { Codigo = 2, Nombre = "Queso1", Descripcion = "Producto Lacteo" }
            );
        }
    }

Cómo vemos en el método Seed, creamos dos producto los cuales necesitamos crear al inicio para nuestro proyecto, adicional podemos ver que el constructor de la clase agregar el atributo AutomaticMigrationDataLossAllowed y lo establecimos en true, esto para asegurarnos que no suceda un error cuando posiblemente se pueda perder información tras una actualización, por ejemplo si decidimos eliminar un campo de alguna tabla tras la actualización nos diría que no se puede actualizar ya que se perdería la información que hay en ese campo, para esto habilitamos este atributo.

Para terminar con la configuración de las migraciones debemos indicar en el constructor de nuestro contexto que la estrategia de inicialización que vamos a usar es MigrateDatabaseToLatestVersion la cual explique anteriormente, y lo hacemos de la siguiente forma:

    public class Context : DbContext
    {
        public Context() : base("Productos")
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<ContextConfiguration>());            
        }
 
        public DbSet<Producto> Productos { getset; }
 
        public DbSet<Categoria> Categorias { getset; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Aquí haremos nuestras configuraciones con Fluent API.
 
            modelBuilder.Configurations.Add(new ProductoMappings());
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.MapLeftKey("IdProducto"));
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.MapRightKey("IdCategoria"));
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.ToTable("ProductosCategorias"));
 
            base.OnModelCreating(modelBuilder);
        }
    }

Ahora podemos crear una app de consola para probar nuestro código y nos daremos cuenta que se creará la base de datos según nuestras configuraciones incluyendo los datos de carga inicial que establecimos en el método Seed, y por ultimo para probar las migraciones podemos eliminar una propiedad de alguna entidad de dominio y veremos que los cambios se ven reflejados en nuestra base de datos.

Y bueno amigos, eso es todo, espero les sea de utilidad y de interés este post acerca de migraciones en Entity Framework code First.

Saludos y buena suerte!

miércoles, 5 de marzo de 2014

[EntityFramework] Configurando una relación de muchos a muchos en Code First

En el artículo anterior vimos cómo configurar una relación de uno a muchos usando Data Annotations y Fluent Api, en esta ocasión vamos a ver cómo configurar una relación de muchos a muchos usando las mismas entidades de dominio Producto y Categoría.

Relación de muchos a muchos mediante Data Annotations:

Para lograr configurar una relación de muchos a muchos en Entity Framework Code First solo debemos agregar una propiedad de tipo colección en cada una de las entidades, obviamente dónde una referencia a la otra, entonces veamos cómo quedarán nuestras entidades Producto y Categoría:

    [Table("Productos")]
    public class Producto
    {
        public Producto()
        {
            Categorias = new HashSet<Categoria>();
        }
 
        [Key]
        public int Codigo { getset; }
 
        [Required]
        [Column("Nombre", TypeName = "varchar", Order = 2)]
        public string Nombre { getset; }
 
        [MaxLength(100), MinLength(10)]
        public string Descripcion { getset; }
 
        [NotMapped]
        public string CodigoIso { getset; }
 
        public virtual ICollection<Categoria> Categorias { getset; }
    }

Cómo podemos ver agregamos la propiedad virtual de tipo ICollection Categoría, y en el constructor inicializamos dicha propiedad para evitar Null Reference Exception cuando agreguemos categorías al producto. Ahora hacemos lo mismo para la entidad Categoría:

    public class Categoria
    {
        public Categoria()
        {
            Productos = new HashSet<Producto>();
        }
 
        [Key]
        public int Id { getset; }
 
        [MaxLength(100)]
        public string Nombre { getset; }
 
        [MaxLength(200)]
        public string Descripcion { getset; }
 
        [Required]
        public virtual ICollection<Producto> Productos { getset; }
    }

Y listo ya con esto tenemos configurada nuestra relación de muchos a muchos entre las entidades Producto y Categoría, para probar vamos a crear una aplicación de consola y copiamos el siguiente código, obviamente con todo el contexto y demás que hemos creado en anteriores ejemplos:

    class Program
    {
        static void Main(string[] args)
        {
            var categoria = new Categoria { Id = 1, Nombre = "Lacteos", Descripcion = "Productos lacteos" };
            var categoria2 = new Categoria { Id = 1, Nombre = "carnes", Descripcion = "Productos carnicos" };
 
            var producto = new Producto { Codigo = 1, Nombre = "Leche", Descripcion = "Producto Lacteo" };
            var producto2 = new Producto { Codigo = 2, Nombre = "Queso", Descripcion = "Producto Lacteo" };
 
            producto.Categorias.Add(categoria);
            producto.Categorias.Add(categoria2);
 
            categoria.Productos.Add(producto);
            categoria.Productos.Add(producto2);
 
            using (var contexto = new Context())
            {
                contexto.Productos.Add(producto);
                contexto.Categorias.Add(categoria);
                contexto.SaveChanges();
            }
        }
    }

Y ahora podemos ver que se han creado las tablas Productos y Categorías, y adicional se creó la tabla ProductoCategorias para representar la relación de muchos a muchos:


Relación de muchos a muchos mediante Fluent Api:

Ahora vamos a configurar la relación de muchos a muchos entre Productos y Categorías, pero esta vez vamos a usar Fluent Api para lograrlo:

    public class Context : DbContext
    {
        public Context() : base("Productos")
        {
            
        }
 
        public DbSet<Producto> Productos { getset; }
 
        public DbSet<Categoria> Categorias { getset; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Aquí haremos nuestras configuraciones con Fluent API.
 
            modelBuilder.Configurations.Add(new ProductoMappings());
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.MapLeftKey("IdProducto"));
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.MapRightKey("IdCategoria"));
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.ToTable("ProductosCategorias"));
 
            base.OnModelCreating(modelBuilder);
        }
    }

Por ultimo si borramos la base de datos anteriormente creada y volvemos a ejecutar el proyecto de consola, veremos que obtendremos los mismos resultados.

Y bueno amigos, eso es todo, espero les sea de utilidad y de interés este post acerca de relación de muchos a muchos en Entity Framework code First, en próximos artículos observaremos más acerca de inicializaciones y migraciones en Code First.

Saludos y buena suerte!