Entity Framework Core 1.0 Migrations in a Separate Class Library

At the beginning of last year I started blogging about ASP.NET Core 1.0 (née ASP.NET 5). But it was early days and things were far from stable with the product, so I soon came to the conclusion that being such an early adopter was more trouble than it was worth due to the number of bugs, missing features, and breaking changes. Roll on a year, and ASP.NET Core 1.0 along with Entity Framework Core 1.0 and the requisite Visual Studio 2015 tooling has finally been released. So time to start playing again.

I can’t say that I’ve done a huge amount with it yet, so can’t really comment on it’s stability. But I would assume that it’s about as stable as you would expect from a 1.0.0 version. Good enough to work with but challenging at times.

And it didn’t take me long to come across a challenge, which I’d like to share with you here.

In any but the smallest of solutions, it’s good practice to seperate data concerns from domain and presentational concerns. In the case of ASP.NET MVC and Entity Framework, that typically involves placing the data context and data model classes into a separate class library.

If I do this and then attempt to add a migration, as follows –

PM> Add-Migration -Name "Initial" -Project "SandboxCore.Data"

I get an error telling me that the preview of EF does not support commands on class library projects –

Could not invoke this command on the startup project 'SandboxCore.Data'. 
This preview of Entity Framework tools does not support commands on class library projects in ASP.NET Core 
and .NET Core applications. See http://go.microsoft.com/fwlink/?LinkId=798221 for details and workarounds.

The link in the error message describes 2 workarounds. However, at the time of writing it is out-of-date, and the workarounds aren’t as simple as described.

So here’s what I believe to be the easiest solution to the problem, which is to create the data project, not as a class library, but as a console application.

1. Add a .NET Core console project, to your solution, to contain the data context and data model classes.

2. Add the entity framework core provider, for your chosen database, as a project dependency to your data project. If targetting SQL Server, add Microsoft.EntityFrameworkCore.SqlServer.

3. Add the entity framework tools, Microsoft.EntityFrameworkCore.Tools, as both a project dependency and as a tool to your data project. Adding it as a project dependency ensures that it is resolved and downloaded from NuGet. Whereas, adding it as a tool ensures that the entity framework commands are accessible. Your data project’s project.json should now look like this –

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.0"
    },
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  },

  "tools": {
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  }
}

4. Add data model classes to your data project. I like to add mine to a Models folder to keep the root of the project tidy.

using System.ComponentModel.DataAnnotations;

namespace SandboxCore.Data.Models
{
    public class Product
    {
        public int ProductId { get; set; }

        [StringLength(200)]
        public string ProductName { get; set; }
    }
}

5. And finally, add an implmentation of DbContext to the data project. The implementation should have a publically accessible Dbset<TEntity> for each data model class, and the OnConfiguring method should be overridden in order to configure the context to target your database of choice. This last part is necessary for migrations.

using Microsoft.EntityFrameworkCore;
using SandboxCore.Data.Models;

namespace SandboxCore.Data
{
    public class SandboxCoreDbContext : DbContext
    {
        public DbSet<Product> Projects { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=SandboxCore;Trusted_Connection=True;");
        }
    }
}

6. You can now enable and add migrations using the following command.

PM> Add-Migration -Name "Initial" -Project "SandboxCore.Data" -StartupProject "SandboxCore.Data"
 

The -Project option specifies SandboxCore.Data as the target for migrations, whilst the -StartupProject option specifies SandboxCore.Data as the entry point for running the EF command.

 

Advertisements

2 thoughts on “Entity Framework Core 1.0 Migrations in a Separate Class Library

  1. I have error: “Your project is not referencing the “.NETFramework,Version=v4.6.1” framework. Add a reference to “.NETFramework,Version=v4.6.1” in the “frameworks” section of your project.json, and then re-run NuGet restore. ….”

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s