Using EF6 with ASP.NET MVC Core 1.0 (aka MVC 6)

This week Microsoft announced that it is renaming ASP.NET 5 to ASP.NET Core 1.0.  In general I think this is a very good step.  Incrementing the version number from 4 to 5 for ASP.NET gave the impression that ASP.NET 5 was a continuation of the prior version and that a clean migration path would exist for upgrading apps from ASP.NET 4 to 5.  However, this did not reflect the reality that ASP.NET 5 was a completely different animal, re-written from the ground up, and that is has little to do architecturally with its predecessor.  I would even go so far as to say it has more in common with node.js than with ASP.NET 4.

You can download the code for this post from my Demo.AspNetCore.EF6 repository on GitHub.

Entity Framework 7, however, has even less in common with its predecessor than does MVC, making it difficult for developers to figure out whether and when they might wish to make the move to the new data platform.  In fact, EF Core 1.0 is still a work in progress and won’t reach real maturity until well after initial RTM.  So I’m especially happy that EF 7 has been renamed EF Core 1.0, and also that MVC 6 is now named MVC Core 1.0.

The problem I have with the name ASP.NET Core is that it implies some equivalency with .NET Core.  But as you see from the diagram below, ASP.NET Core will not only run cross-platform on .NET Core, but you can also target Windows with .NET Framework 4.6.

aspnetcore-mvc-ef.png

Note: This diagram has been updated to reflect that EF Core 1.0 (aka EF 7) is part of ASP.NET Core 1.0 and can target either .NET 4.6 or .NET Core.

It is extremely important to make this distinction, because there are scenarios in which you would like to take advantage of the capabilities of ASP.NET Core, but you’ll need to run on .NET 4.6 in order to make use of libraries that are not available on .NET Core 1.0.

So why would you want to use ASP.NET Core 1.0 and target .NET 4.6?

As I wrote in my last post, WCF Is Dead and Web API Is Dying – Long Live MVC 6, you should avoid using WCF for greenfield web services, because: 1) is it not friendly to dependency injection, 2) it is overly complicated and difficult to use properly, 3) it was designed primarily for use with SOAP (which has fallen out of favor), and 4) because Microsoft appears to not be investing further in WCF.  I also mentioned you should avoid ASP.NET Web API because it has an outdated request pipeline, which does not allow you to apply cross-cutting concerns, such as logging or security, across multiple downstream web frameworks (Web API, MVC, Nancy, etc).  OWIN and Katana were introduced in order to correct this deficiency, but those should be viewed as temporary remedies prior to the release of ASP.NET Core 1.0, which has the same pipeline model as OWIN.

The other important advantage of ASP.NET Core is that it completely decouples you from WCF, IIS and System.Web.dll.  It was kind of a dirty secret that under the covers ASP.NET Web API used WCF for self-hosting, and you would have to configure the WCF binding if you wanted implement things like transport security.  ASP.NET Core has a more flexible hosting model that has no dependence on WCF or System.Web.dll (which carries significant per-request overhead), whether you choose to host in IIS on Windows, or cross-platform in Kestrel on Windows, Mac or Linux.

A good example of why you would want to use ASP.NET Core 1.0 to target .NET 4.6 would be the ability to use Entity Framework 6.x.  The first release of EF Core, for example, won’t include TPC inheritance or M-M relations without extra entities.  As Rowan Miller, a program manager on the EF team, stated:

We won’t be pushing EF7 as the ‘go-to release’ for all platforms at the time of the initial release to support ASP.NET 5. EF7 will be the default data stack for ASP.NET 5 applications, but we will not recommend it as an alternative to EF6 in other applications until we have more functionality implemented.

This means if you are building greenfield web services, but still require the full capabilities of EF 6.x, you’ll want to use ASP.NET MVC Core 1.0 (aka MVC 6) to create Web API’s which depend on .NET 4.6 (by specifying “dnx451” in the project.json file).  This will allow you to add a dependency for the “EntityFramework” NuGet package version “6.1.3-*”.  The main difference is that you’ll probably put your database connection string in an *.json file rather than a web.config file, or you may specify it as an environment variable or retrieve it from a secrets store.  An appsettings.json file, for example, might contain a connection string for a local database file.

{
  "Data": {
    "SampleDb": {
      "ConnectionString": "Data Source=(localdb)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\SampleDb.mdf;Integrated Security=True; MultipleActiveResultSets=True"
    }
  }
}

You can then register your DbContext-derived class with the dependency injection system of ASP.NET Core.

public void ConfigureServices(IServiceCollection services)
{
    // Add DbContext
    services.AddScoped(provider =>
    {
        var connectionString = Configuration["Data:SampleDb:ConnectionString"];
        return new SampleDbContext(connectionString);
    });

    // Add framework services.
    services.AddMvc();
}

This will allow you to inject a SampleDbContext into the constructor of any controller in your app.

[Route("api/[controller]")]
public class ProductsController : Controller
{
    private readonly SampleDbContext _dbContext;

    public ProductsController(SampleDbContext dbContext)
    {
        _dbContext = dbContext;
    }

Lastly, you’ll need to provide some information to EF regarding the provider you’re using (for example, SQL Server, Oracle, MySQL, etc).  In a traditional ASP.NET 4.6 app you would have done that in app.config or web.config.  But in ASP.NET Core you’ll want to specify the provider in a class that inherits from DbConfiguration.

public class DbConfig : DbConfiguration
{
    public DbConfig()
    {
        SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
    }
}

Then you can apply a DbConfigurationType attribute to your DbContext-derived class, so that EF can wire it all together.

[DbConfigurationType(typeof(DbConfig))]
public class SampleDbContext : DbContext
{
    public SampleDbContext(string connectionName) :
        base(connectionName) { }

    public DbSet Products { get; set; }
}

You can download the code for this post from my Demo.AspNetCore.EF6 repository on GitHub.

The primary limitation of targeting .NET 4.6 with EF 6 is that you’ll only be able to deploy your web services on Windows.  The good news, however, is that you’ll be in a great position to migrate from EF 6 to EF Core 1.0 (aka EF 7) as soon as it matures enough to meet your needs.  That’s because the API’s for EF Core are designed to be similar to EF 6.  Then when you do move to EF Core, you’ll be able to use Docker to deploy your web services on Linux VM’s running in a Cloud service such as Amazon EC2, Google Compute Engine, or Microsoft Azure.

About Tony Sneed

Married with three children.
This entry was posted in Technical and tagged , , . Bookmark the permalink.

55 Responses to Using EF6 with ASP.NET MVC Core 1.0 (aka MVC 6)

  1. Bill Noel says:

    Tony,
    I have been having a really hard time getting a clear direction on what my next project should be targeting. Well written and concise. Totally cleared it up for me.
    Thanks!

  2. Hi Tony, nice drawing. I think it would be more correct to place EF7/EF Core together with ASP.NET Core, as it runs on both .NET 4.5+ and .NET Core

  3. AbnerSouza says:

    Is there is a way from VS2015 to create a project using .ASP Core? The option I saw is .Asp 4.6, in this case I think my application is not using the .Net Framework 4.6 and not .Net Core.

  4. Tony Sneed says:

    First make sure you have Visual Studio 2015, then install the ASPNET Core runtime and tooling from here: https://get.asp.net, by clicking “Install for Windows”. You should then see the ASNET6 Preview project templates after first creating a new Web project in Visual Studio. If you don’t see these, then trying installing Microsoft ASP.NET and Web Tools 2015 (RC) – Visual Studio 2015 and selecting the 64 bit MSI installer.

    ASPNET5 Web Project Templates

  5. Danar Jabbar says:

    I think it is time to move to Java.

  6. cmatskas says:

    @Tony, I reckon that core 1.0 is a great stack to work with and a serious contender to Node.js. I’m excited about the prospect and there’s a lot of reasons why this was the right move from the asp.net team. Cross-platform is a serious commitment and one that was done right with Visual Studio Code working hand in hand with the framework

  7. henryqng says:

    Thanks for a very well written article on the new ASP.NET framework.

  8. Pingback: Dew Drop – February 8, 2016 (#2183) | Morning Dew

  9. Kris says:

    Great post.
    Please include PATCH verb use also in your code. That will be great

    • Tony Sneed says:

      The current sample uses PUT instead of PATCH, because setting entity state to Modified will result in replacing all the column values. To use PATCH, you would need to have knowledge of which properties on an entity were modified and instruct EF to do a partial update. PATCH is best accomplished using a framework such as Trackable Entities, but I’m working on a sample using Trackable Entities in the next week, in which I will include a PATCH sample.

  10. Jeroen says:

    Great blog Tony, I managed to integrate EF6 in the “boilerplate” core template. except for “add scaffolding”. i got the menu now by adding some references. except if fails generating the code. it doesnt recognise my dbcontext for DI and when trying to add a new context it complains that i should make shure to have a startup.cs with Configuration property and ConfigureServices . i have all those. Did you manage to get scaffolding menu working?

    • Tony Sneed says:

      I don’t think the ASP.NET scaffolding has been updated to work with ASPNET Core. But I’ll look into it.

    • Tony Sneed says:

      @Jeroen: I’ve checked into it, and it looks like support for adding controllers for ASP.NET Core is supported for plain vanilla Web API controllers, but not with EF6 integration. You can right-click on the Controllers folder, select Add New Item, and then choose “Web API Controller Class”.

      vs2015-aspnet-core-scaffolding

      That will give you a controller with actions for Get, Post, Put and Delete, but you’ll have to manually add your EF code. We’re still early days for ASP.NET Core, so expect to see the VS tooling catch up in the next few months.

  11. Tony Sneed says:

    In case anyone is interested, I created a sample for using Trackable Entities with EF 6 and ASP.NET Core (RC1): https://github.com/tonysneed/Demo.AspNetCore.EF6.Trackable

  12. Paul Thiel says:

    I find it ironic that Microsoft has kept the “ASP.NET” in the new name “ASP.NET Core 1.0″. Prior to that, Microsoft called their MVC product “ASP.NET MVC”. I have thought about this quite a bit and have some thoughts on the subject.

    In the beginning, Microsoft created classic ASP and it was (compared to the other technologies of the time) good. It was also immensely popular. Instead of old CGI applications, web development became easy.

    Over the course of a few years, however, the spaghetti-code nature of classic ASP proved difficult to scale. Microsoft realized this and took their tremendously successful Visual Basic windows development paradigm and extended it to the web with ASP.Net. This solved many of the spaghetti code issues of asp.net by separating the presentation (HTML) from code (Codebehind). Did junior developers still put application code in form events? Yes. Did experienced developers use this to separate their UI from their application logic? Yes.

    This happy state of affairs started 14 years ago and continues to this day for those who develop using web forms. The platform matured, robust 3rd party tool development took place, and there was much rejoicing.

    Alas, during this time, the religious purists noted that some inexperienced programmers put business logic in their codebehind. This was an affront against the separation of concerns god which could not be permitted to stand. Over the course of years, they created the Microsoft version of MVC. No more would programmers put any business logic in their presentation tier (unless it is embedded in the Razor pages making them look suspiciously like classic ASP spaghetti).

    Now, if the purists simply referred to MVC as Microsoft MVC, they knew it wouldn’t be adopted. They knew history, and saw the fate of Microsoft DNA, DCOM, Active X, .Net Remoting, etc…all technologies that were the “new way of doing things” that eventually were discarded as failed experiments. How to avoid this fate for MVC if it didn’t prove to be popular?

    The easy solution is to tag it to probably their most popular development product (ASP.Net) and call it Microsoft ASP.Net MVC. By blurring the lines, they would increase adoption and funnel people into this technology whether they like it or not. Developers would think “if I don’t go this route, I’ll get left behind.” At the same time, they would kill the evil web forms and the unclean codebehind. A two-for-one.

    A funny thing happened, though. People didn’t abandon web forms as the purists intended. The technology split people into two camps. The MVC camp and the webforms camp. The reason for this twofold. The first reason is that for most projects in a business environment, the people paying the bills don’t care what the technology is so long as it works and is stable. Like it or not, web forms are mature and tested. The second reason is that the MVC architecture requires a learning curve for limited benefit (other than pleasing the purists).

    Here’s where it gets really funny. Now we are moving to the new version of ASP.Net. It is not only the “next new thing,” but it is a “complete rewrite from the ground up.” They are pushing this even to the point of calling it Core 1.0. However, like the push to MVC they realize that many developers would prefer to work on a mature and tested platform unless the new platform provides significant advantages (like classic ASP provided over CGI or ASP.Net provided over classic ASP).

    Whatever shall we do? Of course! The new name is not Microsoft Core 1.0. It is Microsoft ASP.Net Core 1.0. Tag the .Net name to it because, let’s face it, developers like .Net. But at the same time, let’s strip it to the bone (and still not get it done on time). Let’s rip out web forms, VB.Net, etc…Wrap it in the ASP.Net wrapper and maybe we will fool those gullible developers again.

    Come on, Microsoft….Just call it ASP.Net for web forms development and Microsoft MVC for MVC development. Good developers will have skills in both, but not be forced into either.

    I’m glad that they are completely branching things even though they are keeping the misleading ASP.Net name. My prediction is that this branch will grow and end at the same dead-end as Active X, Microsoft DNA, etc.. in about 3-5 years. Some variation of web forms will be brought back and touted as a new feature…and the wheel continues to turn.

    Maybe I’m wrong, but I’ve been doing this a long time. Time will tell.

    • Tony Sneed says:

      @Paul, You might be interested in this talk by the architects of ASP.NET vNext on the History of ASP.NET from 1.0 to ASP.NET Core 1.0: https://vimeo.com/154034601.

      My own perspective is that MS will often produce their own version of competing products and platforms which represent paradigm shifts in computing or app development. For example, C# was a response to Java, Silverlight was an answer to Adobe Flash, and ASP.NET Core looks a lot like Node.js.:-) But while it may look like MS is just copying what they see others do, they are responding to real changes in the world. This time around, ASP.NET Core (and indeed .NET Core) is a response to two phenomena: 1) We live in world that is no longer dominated by Windows, and 2) Cloud computing requires a version of .NET which is cross-platform, open-source, modular, and not installed on a per-machine basis.

      Regarding web forms and MVC, the paradigm is now that UI logic takes place client-side via JavaScript, so those are both basically dead for UI dev. MVC generates the UI by sending HTML and JavaScript to the client for non-static pages. MVC is also for what used to be called Web API, that is, RESTful web services which return JSON.

      New paradigms emerge very few years in our business, so yes, get ready for things to continue to change.:-)

  13. This is all great – but since they are getting rid of web.configs, how do deploy systems like Octopus work? Most of the config options I see are based on web.config transforms.

  14. BK says:

    Totally agree with Paul Thiel. It’s time to move back to C++ Qt and PHP. MS have totally thrown what works best in the real world out. Not to mention the myriad of command line changes and project structure changes. Too much , enough is enough !!

    • Tony Sneed says:

      @BK,

      Not to mention the myriad of command line changes and project structure changes. Too much , enough is enough !!

      What makes the changes so difficult this time around is that ASP.NET Core isn’t simply an evolution the MS web dev stack, but it’s a complete re-write of the platform from the ground up, based on a radically different paradigm of cross-platform, cloud-based computing using a microservices architecture with containers like Docker. Not only that, but UI’s rendered on the server are being replaced by rich client-side JavaScript libraries like Angular. The whole project structure and workflow of ASP.NET Core is based on Node.js, so it’s beneficial to learn about Node and NPM in order to feel more comfortable with ASP.NET Core and the way dependencies are managed. Using the API for ASP.NET Core will be easier if you have been using MVC 5 with OWIN and Katana, because the architecture of the middleware-based pipeline is the same.

  15. Danilo Miranda says:

    Hi Tony,
    How to using migration commands in this scenario?
    I tryed some options, but dont have success
    Thanks

    • Tony Sneed says:

      EF 6 migration commands should work the same as before from the Package Console window in Visual Studio, or from a PowerShell command prompt.

      • Allen Rufolo says:

        I’m having issues with the migration commands as well with Visual Studio 2015. I’m getting the following error:

        No DbContext was found. Ensure that you’re using the correct assembly and that the type is neither abstract nor generic.

        I’m not quite sure how to fix this. Any Ideas?

      • Tony Sneed says:

        If you post your question to Stack Overflow, I can address it there .. just post the link here.

  16. William Lane says:

    Hello Tony; great post. I am trying to connect to an Oracle database using EF 6, Oracle.ManagedDataAccess and Oracle.ManagedDataAccess.EntityFramework. I would like to use the EZConnect method but I do not know where to configure the connection values. Do you have an example I could follow?

      • William Lane says:

        I guess I was not clear. I am following your post but would also like to access an Oracle Database in addition to the SQL Server database. I much prefer the Code First approach using Fluent API for the flexibility it provides. I work at a university and we have data in both if you don’t count Active Directory. The SQL Server portion works well. Not so much for the Oracle portion. I thought, from your post, it was a just a matter of correctly defining the Oracle provider. The following is the class I use for the Oracle portion.
        public class OracleDbConfiguration : DbConfiguration
        {
        public OracleDbConfiguration()
        {
        SetProviderServices(“Oracle.ManagedDataAccess.Client”, Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices.Instance);
        SetProviderFactory(“Oracle.ManagedDataAccess.Client”, OracleClientFactory.Instance);
        }
        }

        Does this look correct to you?

      • Tony Sneed says:

        Without trying it, I can’t tell if it will work. But it looks like a good start.:)

  17. sharkey2016 says:

    Hi Tony,
    I am building a green field application, but I would like to get a better separation of the tiers. It seems contrary to good design to have the context injected into the controller. It is easy to do so, but just seems that you lose extensibility by having such fat controllers. I really don’t like having the api having direct interaction with the data access layer. It seems that we are getting right back into tight coupling which I try to avoid. Your thoughts, suggestions are greatly appreciated.

  18. Carl Baron says:

    Had a problem with EF7. I want to do an inner join in the controller and display the results in the view.
    public IActionResult Grid()
    {
    var query = (from pl in db.Authors
    join sm in db.Books on pl.AuthorID equals sm.AuthorID
    select new {LastName = pl.LastName,FirstName = pl.FirstName,Title = sm.Title }).ToList();
    return View(db.Authors);
    }

    @model IEnumerable
    @{
    ViewData[“Title”] = “Database”;
    }
    @ViewData[“Title”].
    @ViewData[“Message”]

    Displaying Data Using the WebGrid Helper

    Authors

    @foreach (var item in Model) {
    @Html.DisplayFor(mode => item.FirstName) @Html.DisplayFor(mode => item.LastName)
    }

    • Carl Baron says:

      I did get it to work. It required research on the web. Microsoft should release good documentation and examples for ASP.NET Core.

  19. sharkey2016 says:

    Hi Tony. I guess I am getting a little bit nervous about the decision to switch dnx for cli. I always thought that RC releases were supposed to be very stable, but this is a big switch from RC1 to RC2 (whenever that is going to happen?). I do not want to be blindsided with a host of changes that would suddenly make our application start failing. I have .net core working with ef6, but my boss is wondering if we should abandon .net core and go back to the previous stable version of .net. Any thoughts, would hate to think that we are going down the wrong path.

    • Tony Sneed says:

      There will be a number of changes to project.json, but the command line is similar, and there shouldn’t be too many API changes. Microsoft promises a migration strategy, which shouldn’t be too onerous. Stick with RC1 until RC2 is released, which should take place in just a few weeks (rumor has it coming out possibly by the end of April or beginning of May, but that’s speculation).

  20. Micheal says:

    @tonysneed PUT /products/5 return 404. What am I missing? though it might be a webdav thing with iis, but I get 404 for kestrel also. I’m using postman, here is the PUT request for {id:5} that I have already posted.

    PUT /api/products/5 HTTP/1.1
    Host: localhost:5000
    Cache-Control: no-cache
    Postman-Token: b1add07d-ecb6-1a51-3015-6900e13f23c6

    {
    “UnitPrice”: 9.99
    }

  21. Joe says:

    Hi Tony,
    I know this comment comes pretty late after you have already posted about using EF6 with ASP.NET Core but I need to ask this: after downloading your sample app from github and looking at it, I see you took a different style to Julie Lerman’s style of combining EF6 and AspNet Core where you don’t have a separate project for your EF specific stuff. Both of you don’t touch on how to use Identity in this scenarios and I would like to know what your advice would be on doing this, where you have EF6 with AspNet Core 1.0 RC2 with Identity working as part of the app.

    Thanks

    • Grzegorz says:

      Hi Tony and Joe,
      I am just facing same problem here. I would like to get familiar with ASP Core by migrating some working project. However, it uses database first model mapping – that’s why I need to use EF6 instead of EFCore. Now I do not know how to integrate Identity with EF6, all samples and libraries for Identity (authentication especially) are based on EFCore. Do you have any advices?

  22. Allen Rufolo says:

    You rock Tony! Thanks a lot for this blog post.

  23. Hi Tony,

    Have you considered how you would unit test projects that are built on ASP.NET Core with Identity and EF6. What would you need to do differently to extract an interface from the DBContext and be able to use this in your Mock Tests. I’m having a play with this at the moment and it’s not as obvious as I would have thought. Would welcome your thoughts.

    Thanks

  24. Hassan Siddique says:

    Hi Tony Sneed ,
    its such an amazing article. You clarify my all confusion about this new asp stack Thanks a lot.
    But Now i have a little confusion in .net-core-rc1 and rc2 and .NetCore App please elaborate it for me

  25. premson says:

    Hi Tony,
    Thanks for this article. I have a scenario which you may be able to give some advice.

    1. MVC core application targets to .net 4.6 (This is basically a container application, say a MVC web host application, so that you just copy Dlls into the application folder and trigger a method you will get new module functionalities )
    2. Service based (interface implementation) Data access layer (based on EF 6 , as in your example)

    As i am not aware of the Database context (which is behind the service layer) to do below

    services.AddScoped(provider =>
    {
    var connectionString = Configuration[“Data:SampleDb:ConnectionString”];
    return new SampleDbContext(connectionString);
    });

    how can we pass the connection string to the context, as in core mvc applications there is no concept of the web.config?

    Thanks.

    • Tony Sneed says:

      How can we pass the connection string to the context, as in core mvc applications there is no concept of the web.config?

      You could write code in your service layer which reads the connection string from where you are storing it, for example, a json.config file. But another approach would be to replace SampleDbContext in the code snippet you referenced with a class in your service layer that can accept a connection string. What you are effectively doing in this case is plugging your service layer into the DI system and supplying a factory method which provides the connection string.

      • premson baby says:

        Thanks for your reply, I ended up doing below.

        Appsettings.Json :
        ===============

        },
        “ConnectionStrings”: {
        “MyTestConnection”: “Server=PS_Premson\\sqlexpress; initial catalog=EFCoreTest2;user id=;password=; MultipleActiveResultSets=True”
        },

        DBContext in DLL project:
        ====================

        public class SampleDbContext : DbContext
        {
        static SampleDbContext()
        {
        Database.SetInitializer(new SampleDbInitializer());
        }

        public SampleDbContext() : base(Connections.GetConnectionString(“MyTestConnection”)) { }

        public DbSet Products { get; set; }
        }

        Helper Class in DLL project :
        =====================

        using Microsoft.Extensions.Configuration;
        using Microsoft.Extensions.PlatformAbstractions;
        public class Connections
        {
        public static IConfigurationRoot Configuration { get; set; }
        public static string GetConnectionString(string connectionStringName)
        {
        var env = PlatformServices.Default.Application;

        string basePath = env.ApplicationBasePath.Substring(0, env.ApplicationBasePath.IndexOf(env.ApplicationName) + env.ApplicationName.Length);

        var builder = new ConfigurationBuilder()
        .SetBasePath(basePath)
        .AddJsonFile(“appsettings.json”)
        .AddEnvironmentVariables();
        Configuration = builder.Build();
        return Configuration.GetConnectionString(connectionStringName);
        }
        }

        Thanks.

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