En este artículo vamos a migrar la aplicación que desarrollamos en el artículo anterior, aprovechando el reciente lanzamiento oficial de Visual Studio 2017, para explorar el proceso de migración, en especial lo referente al cambio del archivo de configuración project.json a <NombreDelProjecto>.csproj.

Puntos Importantes
  1. Tranformaciones del archivo project.json a <Nombre-del-proyecto>.csproj

  2. Se crea un respaldo de todos los archivos migrados

  3. Ventajas del nuevo formato simplificado del archivo <Nombre-del-proyecto>.csproj

  4. Incompatibilidad de EF Core CLI 1.1 en VS 2017, hay que cambiar a 1.0 pero produce los mismos resultados.

Programas fuente

Artículo: EFCoreApp-2.0.zip (release 2.0 del repositorio)
Repositorio: https://github.com/mvelosop/EFCoreApp

Contexto

Paso a paso

1 - Abrir la solución con VS 2017

En cuanto se abre la solución desarrollada con una versión anterior de Visual Studio se observa lo siguiente:

Migrar una aplicación de consola a Visual Studio 2017 /posts/images/devenv_2017-03-13_17-49-26.png

Y a continuación el siguiente informe de conversión:

Migrar una aplicación de consola a Visual Studio 2017 /posts/images/chrome_2017-03-13_17-50-25.png

En este momento ya se realizó la conversión y la solución debería compilar sin problemas.

2 - Explorar los cambios realizados

Importante

Al terminar la conversión se crea una carpeta Backup con los archivos originales de la solución (.sln) y del proyecto (project.json y el .xproj):

Migrar una aplicación de consola a Visual Studio 2017 /posts/images/explorer_2017-03-14_10-03-33.png

También podemos verificar que ahora ya no existe el archivo project.json y en su lugar está el archivo EFCore.App.csproj con el siguiente contenido:

src\EFCore.App\EFCore.App.csproj
[EFCoreApp-2.0]
 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <AssemblyName>EFCore.App</AssemblyName>
    <OutputType>Exe</OutputType>
    <PackageId>EFCore.App</PackageId>
    <RuntimeFrameworkVersion>1.1.1</RuntimeFrameworkVersion>
    <PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
  </PropertyGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1">
      <PrivateAssets>All</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
    <PackageReference Include="System.ComponentModel.Annotations" Version="4.3.0" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
  </ItemGroup>

  <ItemGroup>
    <Folder Include="Migrations\" />
  </ItemGroup>

</Project>

En este archivo hay tres cosas notables:

Importante

En el nuevo formato .csproj no es necesario incluir la lista de todos los archivos de la aplicación, lo mismo que ocurría en el project.json.

  1. Se actualizaron automáticamente todos los paquetes a la versión más reciente (1.1.1).
  2. EL paquete Microsoft.EntityFrameworkCore.Tools.DotNet se “actualizó” hacia abajo a 1.0.0.
  3. No se incluyen las interminables listas de archivos del formato anterior, ¡qué bueno! definitivamente no voy a extrañar los conflictos durante los merge.
Importante

En la migración se cambia la versión de EF Core CLI a 1.0, porque la versión 1.1 no maneja el archivo .csproj

Al ejecutar dotnet ef verificamos que efectivamente se trata de la versión 1.0.0:

Migrar una aplicación de consola a Visual Studio 2017 /posts/images/cmd_2017-03-14_10-43-14.png

3 - Verificar funcionamiento de EF Core

Sólo para verificar el funcionamiento del CLI de EF, eliminamos el contenido de la carpeta Migrations, para volver a generar la migración, y ejecutamos dotnet ef migrations add InitialCreateMigration y se generan los siguientes archivos:

Migrations/CommonDbContextModelSnapshot.cs

src\EFCore.App\Migrations\CommonDbContextModelSnapshot.cs
[EFCoreApp-2.0]
 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243444546474849
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.1")
                .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");
                });
        }
    }
}

Como era de esperar, este archivo es igual al de la versión anterior con la única excepción de la línea que indica:

.HasAnnotation("ProductVersion", "1.1.1")

De la misma forma, el nuevo archivo de la migración sólo se diferencia en el nombre, por la nueva fecha de creación:

Migrations/20170314105415_InitialCreateMigration.cs

src\EFCore.App\Migrations\20170314105415_InitialCreateMigration.cs
[EFCoreApp-2.0]
 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344454647
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");
        }
    }
}

Para verificar que todo sigue funcionando correctamente, eliminamos la base de datos EFCore.App y ejecutamos el programa con [Ctrl]+[F5] y obtenemos el resultado esperado:

Migrar una aplicación de consola a Visual Studio 2017 /posts/images/cmd_2017-03-14_11-07-49.png

Así que, de aquí en adelante, a menos que no se pueda para algún tema en particular, seguiremos trabajando con Visual Studio 2017.


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.