Quick Tip: Entity Framework Core Models In Class Library

If you are looking for a way to convert your existing Entity Framework data layer to Core 1.0, you may run into some issues. Today, I provide a workaround thanks to a fellow blogger.

Written by Jonathan "JD" Danylko • Last Updated: • Develop •
Lego character holding a ctrl key from keyboard

Over this past months, I've been slowly converting my CMS over to ASP.NET MVC/EF/Identity Core 1.0 and implementing pieces as they become more stable.

This weekend, I was wrestling with an issue of generating Entity Framework Entities in an ASP.NET Core 1.0 Class Library.

I wanted to keep my data layer in a separate assembly because, well...you know, it's like an onion.

Thinking I could generate my new entities using the dnx ef scaffold dbcontext technique from before, I tried it.

Just call me Mr. Optimist, but it didn't work.

I was going through everything in my head.

"Ok, do we have everything to generate the entities?"

"Am I missing an assembly?"

Check the project.json

After thinking I didn't have an assembly installed, I looked over the project.json file to see what was missing.

project.json

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.0",
      "type": "platform"
    },
    "Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
    "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.0",
    "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
    "Microsoft.AspNetCore.Routing.Abstractions": "1.0.0",
    "Microsoft.AspNetCore.Mvc.Abstractions": "1.0.0",
    "System.Collections.Specialized": "4.0.1",
    "Microsoft.AspNetCore.Mvc.ViewFeatures": "1.0.0",
    "System.Linq.Queryable": "4.0.1",
    "System.Xml.XmlDocument": "4.0.1"
  },
  "tools": {
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  },
  "frameworks": {
    "netcoreapp1.0": {}
  }
}

Nope, nothing looked weird in the project.json.

Next, Try to Generate the Entities...Again

With the project.json in good shape, I tried to generate the entities again by using the command-line in the project directory.

dotnet ef dbcontext scaffold "server=localhost;database=myDatabaseName;Trusted_Connection=true;" Microsoft.EntityFrameworkCore.SqlServer --output-dir Models/EF

After waiting for a couple of seconds, I receive this little message:

error CS5001: Program does not contain a static 'Main' method suitable for an entry point

Umm...you are correct because it's a class library, not an executable.

Ok, that didn't work.

My Last Resort: "Oh Gooooogle?"

In a last ditch effort, I kept asking Ash and Coulson what they thought. They were no help! :-p

So I decided to talk to my other best friend, Google.

After searching for 15 minutes, I found a well-written post by Ben Cull about Entity Framework Core Migrations in Class Library Projects.

It seems this is an issue with EF Migrations Core RTM and it is acknowledged as a problem. They are working on it.

Right now, there is a workaround. You need a static void Main() in an empty Program.cs and place it into your root of the Class Library.

public class Program
{
    // - Taken from http://benjii.me/2016/06/entity-framework-core-migrations-for-class-library-projects/
    //   to make EF work.
    // - Used this to generate EF scaffolding at the command line in the root of the project:
    //     dotnet ef dbcontext scaffold "server=localhost;database=MyDatabaseName;Trusted_Connection=true;" Microsoft.EntityFrameworkCore.SqlServer --output-dir Models/EF
    public static void Main(string[] args)
    {
    }
}

That Was It

Re-run your dotnet ef dbcontext scaffold command from above at the command-line. It will recompile your code and everything should be ok.

One last thing that Ben mentions is that our fake app (the Program.cs) needs to know how to create a DbContext.

Lastly, we need to let our fake app know how to create your DbContext. The tools would normally gather this information from your startup.cs, but since that would be a huge pain to implement, let’s cheat and create an IDbContextFactory instead.

Add the following class to your class library:

public class TemporaryDbContextFactory : IDbContextFactory<PinchContext>
{
    public PinchContext Create(DbContextFactoryOptions options)
    {
        var builder = new DbContextOptionsBuilder<PinchContext>();
        builder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=pinchdb;Trusted_Connection=True;MultipleActiveResultSets=true");
        return new PinchContext(builder.Options);
    }
}

Thanks, Ben (@BenWhoLikesBeer) for getting me back on track with EF Core.

Did you like this content? Show your support by buying me a coffee.

Buy me a coffee  Buy me a coffee
Picture of Jonathan "JD" Danylko

Jonathan Danylko is a web architect and entrepreneur who's been programming for over 25 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Principal Software Engineer Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus