En este artículo desarrollamos una aplicación de consola sencilla, usando Code First con EF Core 1.1, con el fin explorar algunos aspectos básicos del trabajo con EF Core.
Puntos Importantes
Paquetes mínimos necesarios para trabajar con EF Core.
Clases de configuración con Fluent API.
Leer string de conexión de archivos configuración.
Usar de EF Core CLI para crear la migración inicial.
Crear automáticamente la base de datos.
Programas fuente
Artículo: EFCoreApp-1.0.zip (release 1.0 del repositorio)
Repositorio: https://github.com/mvelosop/EFCoreApp
Contexto
Para seguir este artículo es necesario tener instalado lo siguiente:
Herramientas
.NET Core 1.1
- Visual Studio 2015 Tools (Preview 2)
- .NET Core 1.1 SDK - Installer x64
- .NET Core 1.1 runtime - Installer x64
(Este es necesario, además del SDK, para soportar .NET Core 1.1)
Paso a paso
1 - Crear la solución EFCoreApp
- Crear una solución “blank” llamada EFCoreApp
- Crear el solution folder “src”
- Crear la carpeta “src” dentro de la carpeta de la solución
2 - Crear proyecto src/EFCore.App
- Crear el proyecto como una “Console Application (.NET Core)”
Actualizar project.json a lo siguiente:
project.json[EFCoreApp-1.0] src\EFCore.App\1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
{ "buildOptions": { "copyToOutput": { "include": [ "appsettings.json" ] }, "emitEntryPoint": true }, "dependencies": { "Microsoft.EntityFrameworkCore": "1.1.0", "Microsoft.EntityFrameworkCore.Design": { "type": "build", "version": "1.1.0" }, "Microsoft.EntityFrameworkCore.SqlServer": "1.1.0", "Microsoft.Extensions.Configuration": "1.1.0", "Microsoft.Extensions.Configuration.Binder": "1.1.0", "Microsoft.Extensions.Configuration.Json": "1.1.0", "Microsoft.NETCore.App": { "type": "platform", "version": "1.1.0" }, "System.ComponentModel.Annotations": "4.3.0" }, "frameworks": { "netcoreapp1.0": { "imports": "dnxcore50" } }, "tools": { "Microsoft.EntityFrameworkCore.Tools.DotNet": "1.1.0-preview4-final" }, "version": "1.0.0-*" }
Salvar el archivo desde VS para actualizar todos los paquetes o, si prefiere usar la interfaz de comandos de desarrollo ([Shift]+[Alt]+[,]), ejecute
dotnet restore
Detalles de project.json
ImportanteAquí vemos los paquetes mínimos necesarios para trabajar con EF Core
Paquetes de Entity Framework Core
- Microsoft.EntityFrameworkCore: Paquete base
- Microsoft.EntityFrameworkCore.Design: Componentes para EF Core CLI, sólo para desarrollo, por eso
"type": "build"
- Microsoft.EntityFrameworkCore.Tools.DotNet: EF Core CLI
- Microsoft.EntityFrameworkCore.SqlServer: SQL Server provider
Paquetes para manejar archivos de configuración
- Microsoft.Extensions.Configuration: Paquete base
- Microsoft.Extensions.Configuration.Binder: Para manejar configuraciones “strongly typed”.
- Microsoft.Extensions.Configuration.Json: Manejo de archivos json
Otros
- System.ComponentModel.Annotations: Annotations para los modelos
- System.ComponentModel.Annotations: Annotations para los modelos
3 - Agregar archivos del proyecto
Model\Currency.cs
La clase del modelo, Divisas en este caso.
|
|
Base\EntityTypeConfiguration.cs
ImportanteEstas clases permiten manejar una clase de configuración por cada clase del modelo, para mantener el DbContext lo más sencillo posible, de forma similar a como se puede hacer con EF 6, según lo sugerido en https://github.com/aspnet/EntityFramework/issues/2805
|
|
Data\CurrencyConfiguration.cs
ImportanteLa clase de configuración del modelo permite mantener fuera del DbContext los detalles de cada clase. Esto simplifica mucho el DbContext.
|
|
Config\ConfigClasses.cs
ImportanteAquí vemos como podemos manejar las opciones de configuración a través de clases auxiliares, para hacerlo de forma “strongly typed”.
Clases de configuración de la aplicación, permiten manejar la configuraciones que se carguen del archivo appsettings.json de una forma “strongly typed”.
|
|
Data\CommonDbContext.cs
El DbContext para la aplicación, define la vista de la base de datos a la que tiene acceso la aplicación.
|
|
Program.cs
ImportanteEl método InitDb crea la base de datos o aplica las migraciones necesarias al arrancar la aplicación, en vez de hacerlo con el primer request. Esto mejora la experiencia del usuario.
El programa principal de la aplicación. Aquí están los métodos que crean/actualizan la base de datos y realizar la carga de datos iniciales.
|
|
4 - Generar la migración inicial
ImportanteAquí vemos la forma general de trabajar con el EF Core CLI.
Siempre podemos usar
dotnet ef <comando> -h
para consultar la ayuda del comando.Ahora es necesario generar la migración inicial que utilizará EF para crear la base de datos cuando se ejecute la aplicación por primera vez.
Abrir la interfaz de comandos de desarrollo
- Hacer click sobre el nodo del proyecto EFCore.App en el explorador de la solución.
- Pulsar [Shift]+[Alt]+[,] o Botón derecho > Open Command Line > Developer Command Prompt
- Ejecutar
dotnet ef
- Si todo marchó bien, debe observar una pantalla similar a la siguiente:
Crear la migración inicial
- Ejecutar
dotnet ef migrations add InitialCreateMigration
en la interfaz de comandos.- Se puede utilizar cualquier nombre para la clase de la migración, pero recomiendo utilizar el sufijo “Migration” para evitar conflictos de nombres con otras clases de la aplicación.
- También podemos utilizar
dotnet ef [comando] --help
para consultar la ayuda de cualquier comando de la interfaz.Verificar que se hayan creado los archivos de la migración inicial, en la carpeta Migrations, similar a los siguientes:
Migrations\CommonDbContextModelSnapshot.cs
Este archivo es la configuración de la última versión del modelo, se utiliza al ejecutar el método DbContext.Database.EnsureCreated().
Observe que en esta clase está consolidada toda la definición de los objetos de base de datos, usando Fluent API, incluyendo los atributos utilizados en las propiedades del modelo de dominio.
CommonDbContextModelSnapshot.cs[EFCoreApp-1.0] src\EFCore.App\Migrations\
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using EFCore.App.Data; namespace EFCore.App.Migrations { [DbContext(typeof(CommonDbContext))] partial class CommonDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { modelBuilder .HasAnnotation("ProductVersion", "1.1.0-rtm-22752") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("EFCore.App.Model.Currency", b => { b.Property<int>("Id") .ValueGeneratedOnAdd(); b.Property<string>("IsoCode") .IsRequired() .HasMaxLength(3); b.Property<string>("Name") .IsRequired() .HasMaxLength(100); b.Property<byte[]>("RowVersion") .IsConcurrencyToken() .ValueGeneratedOnAddOrUpdate(); b.Property<string>("Symbol") .IsRequired() .HasMaxLength(10); b.HasKey("Id"); b.HasIndex("IsoCode") .IsUnique(); b.ToTable("Currencies","Common"); }); } } }
Migrations\20170227231210_InitialCreateMigration
Este archivo es el encargado de generar la migración desde la versión anterior de CommonDbContextModelSnapshot.cs, se utiliza al ejecutar el método DbContext.Database.Migrate().
Los números iniciales del nombre indican el año-mes-día-hora-minuto-segundo (yyyyMMddHHmmss) de generación de la migración.
20170227231210_InitialCreateMigration.cs[EFCoreApp-1.0] src\EFCore.App\Migrations\
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Metadata; namespace EFCore.App.Migrations { public partial class InitialCreateMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.EnsureSchema( name: "Common"); migrationBuilder.CreateTable( name: "Currencies", schema: "Common", columns: table => new { Id = table.Column<int>(nullable: false) .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), IsoCode = table.Column<string>(maxLength: 3, nullable: false), Name = table.Column<string>(maxLength: 100, nullable: false), RowVersion = table.Column<byte[]>(rowVersion: true, nullable: true), Symbol = table.Column<string>(maxLength: 10, nullable: false) }, constraints: table => { table.PrimaryKey("PK_Currencies", x => x.Id); }); migrationBuilder.CreateIndex( name: "IX_Currencies_IsoCode", schema: "Common", table: "Currencies", column: "IsoCode", unique: true); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "Currencies", schema: "Common"); } } }
5 - Crear archivo de configuración
appsettings.json
Este string de conexión es adecuado para SQL Server Developer Edition con la instancia por default (MSSQLSERVER), puede ser necesario ajustarlo si la situación es distinta.
appsettings.json[EFCoreApp-1.0] src\EFCore.App\
1 2 3 4 5
{ "connectionStrings": { "defaultConnection": "Data Source=localhost;Initial Catalog=EFCore.App;Integrated Security=SSPI;" } }
Verificar que project.json incluya la opción para copiar este archivo a la carpeta de salida:
"buildOptions": { "copyToOutput": { "include": [ "appsettings.json" ] }, "emitEntryPoint": true },
6 - Ejecutar la aplicación
Suponiendo que ya se instaló el SQL Server 2016 Developer Edition, al ejecutar la aplicación con [Ctrl]+[F5] se debe obtener una salida similar a esta:
Y si en algún momento necesitamos empezar con una base de datos nueva, basta con eliminarla usando el SQL Server Management Studio y ejecutar la aplicación de nuevo.
Espero que este artículo le haya resultado útil y le invito a darme su opinión en la sección de comentarios.
Gracias,
Miguel.Enlaces relacionados
.NET Core current downloads
https://www.microsoft.com/net/download/core#/current
.NET Core EF CLI
https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet