Posts
1150
Comments
891
Trackbacks
1
Using EF 6 with Asp.Net 5 MVC 6

Just an aside, but Microsoft’s naming conventions are getting absolutely comical.

Anyhoo….Microsoft appears to hate connection strings now.  With UWP and now with Asp.Net 5 MVC 6, they just don’t make things easy at all.

Since EF 7 is woefully undeveloped, and even when it RTMs, it won’t be ready for prime-time, I was trying to get an existing EF 6 infrastructure to work with WebAPI in the new Asp.Net 5 MVC 6 world (yes, I’m going to keep typing it out).  Since code changes are fun, there were various changes that needed to be made to take a WebApi 2 application itself and convert it (lots of changing IHttpActionResult to IActionResult…why?  Why not?).  And, dear Microsoft, why do I need to AddMvc and then UseMvc?  Really?

But when it came to reusing EF 6, there were additional challenges.  The built in auto-wiring fantastic joy stuff only works with EF 7.  You can reference EF 6 from NuGet, that’s not a problem.

But (he repeats himself), Asp.Net 5 MVC 6 doesn’t like web.config anymore.  There is one that sits in wwwroot (what the heck is it for, he wonders), but you can’t put connection strings in.  I mean, you can, but they are ignored.   Instead, Asp.Net 5 MVC 6 likes you to put things in appsettings.json and do stuff with it in startup.cs, but that doesn’t work well when you need to new up a DataContext in your controller.

I name my DataContext things like “InfrastructureConnectionSettings”, and I create the connection strings off of a Data Model such that they look like this in web.config:

<add name="InfrastructureConnectionSettings" connectionString="metadata=res://*/Infrastructure.csdl|res://*/Infrastructure.ssdl|res://*/Infrastructure.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=myServer;initial catalog=myDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient"/>

And then, my controller will have a private DataContext like this:

private InfrastructureConnectionSettings db = new InfrastructureConnectionSettings();

And then I can do things like:

return db.ErrorLogs.Take(3).OrderByDescending(x => x.DateCreated);

But, if you try to run this in Asp.Net 5 MVC 6, it will tell you it can’t find an entry for “InfrastructureConnectionSettings” in the application configuration file.  Which is true, because there isn’t one.

Instead, you need to create a new partial class with a constructor like this:

public InfrastructureConnectionSettings(string connectionString): base(connectionString)
        {
        }

And then in your controller you can do something like this (to test):

private InfrastructureConnectionSettings db = new InfrastructureConnectionSettings("metadata=res://*/Infrastructure.csdl|res://*/Infrastructure.ssdl|res://*/Infrastructure.msl;provider=System.Data.SqlClient;provider connection string='data source=myServer;initial catalog=myDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework';");

And, note here that there are actual single quotes instead of %quot around the connection string itself.  It sucks to have to put in any connection string information inside the controller (even pulling from configuration in each controller is bad), but at least it works.

 So, how to do it slightly (and only slightly) better?

Define a class:

public class AppSettings
   {
       public string InfrastructureConnectionSettings { get; set; }
   }

Do these things in startup.cs:

services.AddOptions();
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

And now, in your controller, do this:

public ErrorLogController(IOptions<AppSettings> appSettings)
        {
            db = new InfrastructureConnectionSettings(appSettings.Value.InfrastructureConnectionSettings);
        }

And put your values in appsettings.json like this:

{
  "AppSettings": {
    "InfrastructureConnectionSettings": "metadata=res://*/Infrastructure.csdl|res://*/Infrastructure.ssdl|res://*/Infrastructure.msl;provider=System.Data.SqlClient;provider connection string='data source=myServer;initial catalog=myDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework';"
  }
}

And there you go.  What used to be a simple entry in your web.config, recreated in 17 steps or so.  Because web.config isn’t testable.  Brilliant.

posted on Friday, December 25, 2015 11:59 PM Print
Comments
No comments posted yet.

Post Comment

Title *
Name *
Email
Url
Comment *  
Please add 8 and 2 and type the answer here: