ASP.NET 5 and AngularJS Part 4, Using Entity Framework 7

This is the fourth part in a multiple part blog series on building ASP.NET 5 (ASP.NET vNext) apps with AngularJS. In this series of blog posts, I show how you can create a simple Movie app using ASP.NET 5, MVC 6, and AngularJS.

You can download the code discussed in this blog post from GitHub:

https://github.com/StephenWalther/MovieAngularJSApp

In this blog post, I explain how to use Entity Framework 7 to persist the movie data to a database.

Adding the Entity Framework NuGet Packages

Before you can use the Entity Framework, you must add the Entity Framework 7 NuGet packages to your project. Ensure that your project.json file includes the following two dependencies (you’ll get Intellisense while entering the names of the packages and their versions).

"EntityFramework.SqlServer": "7.0.0-beta2",
"EntityFramework.Commands": "7.0.0-beta2",

After you complete this step, the Entity Framework packages should appear under References:

EFReferences

Creating the Model and DbContext

Next, we need to create our Movie model class. This class represents the entity that we want to store in the database. Add the following Movie.cs class to your Models folder:

namespace MovieAngularJSApp.Models
{
    public class Movie
    {
        public int Id { get; set; }

        public string Title { get; set; }

        public string Director { get; set; }
    }
}

We also need to create an Entity Framework DbContext class. We create this class when using Entity Framework 7 in exactly the same way as we created this class for previous versions of the Entity Framework.

using Microsoft.Data.Entity;

namespace MovieAngularJSApp.Models
{
    public class MoviesAppContext:DbContext
    {

		public DbSet<Movie> Movies { get; set; }

	}
}

Registering the Entity Framework Services

Now that we have our DbContext class, we need to register the DbContext with our application services. Modify your Startup.cs file so it contains the code for registering the Entity Framework in the code below:

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Data.Entity;
using MovieAngularJSApp.Models;
using Microsoft.AspNet.Hosting;
using Microsoft.Framework.ConfigurationModel;



namespace MovieAngularJSApp
{
	public class Startup
	{
		public Startup(IHostingEnvironment env)
		{
			// Setup configuration sources.
			Configuration = new Configuration()
				.AddJsonFile("config.json")
				.AddEnvironmentVariables();
		}

		public IConfiguration Configuration { get; set; }


		public void ConfigureServices(IServiceCollection services)
		{
			services.AddMvc();

			// Register Entity Framework
			services.AddEntityFramework(Configuration)
				.AddSqlServer()
				.AddDbContext<MoviesAppContext>();
		}

		public void Configure(IApplicationBuilder app)
		{
			app.UseMvc();
        }

	}
}

The database connection string is loaded up from the Config.json file (notice the constructor in the Startup.cs file). Here is what the Config.json file looks like:

{
    "Data": {
        "DefaultConnection": { 
            "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MoviesDatabase;Trusted_Connection=True;MultipleActiveResultSets=true"
        }
    },
    "EntityFramework": {
        "MoviesAppContext": {
            "ConnectionStringKey": "Data:DefaultConnection:ConnectionString"
        }
    }
}

Updating the MoviesController

Because we registered our MoviesAppContext class as a service, we can take advantage of the built-in ASP.NET 5 Dependency Injection framework to use the MoviesAppContext in our MoviesController. Notice that the MoviesAppContext class is added to the MoviesController using constructor dependency injection in the code below:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc;
using MovieAngularJSApp.Models;


namespace MovieAngularJSApp.API.Controllers
{
    [Route("api/[controller]")]
    public class MoviesController : Controller
    {
		private readonly MoviesAppContext _dbContext;

		public MoviesController(MoviesAppContext dbContext) 
		{
			_dbContext = dbContext;
		}

        [HttpGet]
        public IEnumerable<Movie> Get()
        {
			return _dbContext.Movies;
        }


        [HttpGet("{id:int}")]
        public IActionResult Get(int id)
        {
			var movie = _dbContext.Movies.FirstOrDefault(m => m.Id == id);
			if (movie == null) {
				return new HttpNotFoundResult();
			} else {
				return new ObjectResult(movie);
            } 
		}


        [HttpPost]
        public IActionResult Post([FromBody]Movie movie)
        {
			if (movie.Id == 0)
			{
				_dbContext.Movies.Add(movie);
				_dbContext.SaveChanges();
				return new ObjectResult(movie);
			}
			else
			{
				var original = _dbContext.Movies.FirstOrDefault(m => m.Id == movie.Id);
				original.Title = movie.Title;
				original.Director = movie.Director;
				_dbContext.SaveChanges();
				return new ObjectResult(original);
			}
        }


        [HttpDelete("{id:int}")]
        public IActionResult Delete(int id)
        {
			var movie = _dbContext.Movies.FirstOrDefault(m => m.Id == id);
			_dbContext.Movies.Remove(movie);
			_dbContext.SaveChanges();
            return new HttpStatusCodeResult(200);
        }


    }
}

Performing Database Migrations

After we complete all of the steps above, our application still won’t work. If we run the Movies app then we will get an error message about not being able to open the MoviesDatabase.

NoDBError

Unlike previous versions of the Entity Framework, the Entity Framework 7 does not support database initializers. Instead, you are encouraged to use Database Migrations.

There are two ways to use Migrations with ASP.NET 5: from a Command Prompt or from the NuGet Package Manager Console. You can read the details about each approach by reading Brice Lam’s blog at the following addresses:

http://bricelam.net/2014/10/22/ef7-nuget-commands.html
http://bricelam.net/2014/09/14/migrations-on-k.html

Here, I used the Command Prompt approach and I executed the following two commands from the same directory that contains my project.json file:

k ef migration add initial
k ef migration apply

KPrompt

After you execute the two ef commands above, a new database named MoviesDatabase will be created. You can see the new database by opening up the Visual Studio SQL Server Object Explorer:

SQLExplorer

Executing the ef commands above will also add a new Migrations folder to your project.

Migrations

You now should be able to run the Movies app successfully. When you click the Add button, you should be able to add a new movie to the database. You also should be able to edit and delete movies.

MoviesAppWorking

Summary

In this blog post, I focused on using ASP.NET 5 with Entity Framework 7. I explained how you can add the NuGet packages for Entity Framework 7 and register the Entity Framework services in your Startup.cs file. Finally, I showed you how to use Migrations to initialize a new database.

In the next blog post, I will focus on the topic of client-side and server-side validation.

Discussion

  1. ARD says:

    Probably a stupid question but I am not sure how to get the “k” command working on command prompt. Those two links didn’t fully help either. Do I need to install something?

  2. @ARD — The K command line tool is installed automatically when you install VS 2015. Alternatively, you can download and install with powershell without installing VS 2015. There are instructions here https://github.com/aspnet/Home

  3. ARD says:

    Thanks. Its working now.

  4. Steven says:

    System.InvalidOperationException: No service for type ‘Microsoft.Data.Entity.Inf
    rastructure.DbContextService`1[Microsoft.Data.Entity.Migrations.Infrastructure.M
    igrator]’ has been registered.

  5. Steven says:

    k ef migration initial

    is throwing the error

    System.InvalidOperationException: No service for type ‘Microsoft.Data.Entity.Inf
    rastructure.DbContextService`1[Microsoft.Data.Entity.Migrations.Infrastructure.M
    igrator]’ has been registered.