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.

ASP.NET 8 Best Practices on Amazon

ASP.NET 8 Best Practices by Jonathan Danylko


Reviewed as a "comprehensive guide" and a "roadmap to excellence" with over 120 Best Practices for ASP.NET Core 8, Jonathan's first book by Packt Publishing explores proven techniques for every phase of the SDLC.

Learn industry-standard concepts to improve your coding, debugging, and deployment of ASP.NET Core websites.

Order now on Amazon.com button

Picture of Jonathan "JD" Danylko

Jonathan "JD" Danylko is an author, web architect, and entrepreneur who's been programming for over 30 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an 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