A Look at ASP.NET 5: Part 3 - EF7

Every web project needs some sort of data framework and ASP.NET 5 is no exception. Like it’s forbearers, ASP.NET 5 uses Entity Framework, but this version of the Entity Framework is different. It’s being re-engineered from the ground up just like the ASP.NET 5 stack.

In this, the third part of my ASP.NET 5 series, I’ll be talking about Entity Framework 7. While you can use older versions of EF or other storage mechanisms (NoSQL, Postgres, etc.), I think it’s an interesting exercise to see what the EF team is thinking in this evolving version of the framework.

I’ll explain what I’m doing in a series of blog posts and link them all here as I write them. The plan is to write posts about:

First thing to understand is that EF7 isn’t done. It’s a work in progress. So much of the warts and pain points I discuss here will hopefully be gone by the time you’re actually using the framework in ASP.NET 5 projects.

Configuring Entity Framework

To get started with Entity Framework 7, you need the reference. By default this is already there but for when you need to update to new versions, I thought I’d point it out where it is in the project.json file:

If you remember the last post, the startup.cs allowed for configuration to happen in two phases. First the configuration of the different elements, then the registering of services with the dependency injection layer. So let’s start there.

The service container is the dependency injection mechanism built into ASP.NET 5 and the ConfigureServices method is where that happens. Before we can add EF to the DI container, we need to get a connection string.

When I first came to ASP.NET 5, it looked as if the EF configuration would just load the connection string by convention, but it didn’t work. So I had to get it manually and add it (below) when I configured the context object. So, instead, I just grabbed it from the Configuration object that was created in the constructor:

The Configuration.Get method allows it to read a setting from the list of configuration

sources. If you remember from the last post, the Configuration object is a merge of the config.json file and any environment variables. In the case of the connection string, we’re looking for a string called “ConnectionString” inside an object graph. This should look obvious once you see the config.json file:

The AddEntityFramework method adds EF to the dependency injection container so it can be served if needed later. Additionally, calling AddSqlServer specifies the data store you’ll be using. Finally, the AddDbContext adds a DbContext object to the EF service (we’ll get to what that looks like below). The options lambda allows us to specify the connection string. I suspect this extra step will go away at some point and just read from the configuration by convention, but at this point it’s necessary. At this point, if we need the context in another part of the system (e.g. Controllers) we can just let ASP.NET 5 serve it to us in the constructor like any other dependency injection framework.

Creating the DbContext

Assuming you’re somewhat familiar with Entity Framework, you should already know that the DbContext class has the responsibility of exposing the data in a data store via the Code-First semantics. Creating a DbContext derived class hasn’t changed substantially.

The Database.EnsureCreated is important because it causes the database to be created and migrations to be run to make sure the database is up to date as well.

But this isn’t quite what I did. Originally, the project template created a context for the ASP.NET Identity system that derived from IdentityContext. but I didn’t want to have two disconnected DbContext classes. Instead of creating a new context like this, I just combined the two so that one context would be responsible for Identity and my own data (e.g. the Visits DbSet). I did this by deriving my context from IdentityContext as shown here:

Because I created a repository class that does the real work of the site, I’ll need to configure that in the ConfigureService method too. In this case, it’s a simple adding of the interface and implementation class like any other dependency injection framework you’ve used before (i.e. Ninject, Unity, etc.):

So that when I have a class that requires the IMyCountriesRepository, it passed in an instance of the MyCountriesRepository class as you’d expect. And since it is handling the dependency chains, it will fulfill any requirements that the repository class have (e.g. will pass in a created MyCountriesContext to the repository as that is a dependency of that class).

This implies something that is important:

If you’re not using dependency injection yet, get used to it…you’ll be doing it in ASP.NET 5!

Database Initialization in EF7 Today

In the creation of the DbContext, we saw that the code is calling Database.EnsureCreated() to cause the database to be created. What isn’t obvious here is that it also calls Migrations. Migrations are used to build the schema of your entities. But we need the migration to exist. Because I started this project back in an early beta, I’ve had to delete the entire set of migrations (the code in the Migrations folder) and rebuild the migrations a few times. Once we reach release, this won’t be as much of an issue.

For seeding we have another problem. If you’ve done Entity Framework code before, you might be using the DbInitializer pattern to create the database and seed it. I am not sure if this part of EF7 isn’t done or whether they decided to just give you more control over the process, but in either case I needed a way to initialize the database creation and seeded data. Let’s see how I accomplished it.

The DbContext class I created looks different from the original one that the template project created. That’s because originally there was a hack in the code to allow you to create the database if necessary. I didn’t like how this worked so I broke out it into it’s own code.

I created a class called SampleData that is used to create the database and seed it if necessary. I created it as a static class, but you can do it whatever way you want. I started with a static method called InitializeData:

Because the calls to CreateAsync and AddClaimAsync requires me to use async, the method also has to be async.

So now that I have the SampleDataInitializer class, how do I call it. For me, I just called it in the startup.cs. (A bit brute force? Sure.) But the challenge was how to create an instance of the SampleDataInitializer using the dependency injection system to fulfill my dependencies?

The trick is to use the ConfigureServices dependency registration. You can simple add it via AddTransient so that it’s created when you need it (and we’ll only need it once when the server is started):

// This method gets called by the runtime.
public void ConfigureServices(IServiceCollection services)
{
// ...
// Add other services
services.AddTransient<SampleDataInitializer>();

Once that is registered, I can just use parameter injection to add it to the configure method (note the new SampleDataInitializer parameter):

Note that I changed the Configure to decorate it with async since our call to InitializeDataAsync requires async/await. Now we can just use the initializer to initialize the data like so (somewhere in the Configure, I do it as the last step:

Ready to Learn Vue with ASP.NET Core?

Shawn's 4-hour course will get you up to speed in no time. Vue.js is a great middle-ground between React and Angular for people who don't like the complexity of Angular, and the overly componentized React. Learn today at Wilder Minds Training!