Caution

This documentation is for EF7 onwards. For EF6.x and earlier release see http://msdn.com/data/ef.

Note

This article uses EF 7.0.0-rc1 which is the latest pre-release available on NuGet.org. You can find nightly builds of the EF7 code base hosted on https://www.myget.org/F/aspnetvnext/ but we do not maintain up-to-date documentation for nightly builds.

ASP.NET 5 Application to Existing Database (Database First)

In this walkthrough, you will build an ASP.NET 5 MVC application that performs basic data access using Entity Framework. You will use reverse engineering to create an Entity Framework model based on an existing database.

In this article:

Tip

You can view this article’s sample on GitHub.

Prerequisites

The following prerequisites are needed to complete this walkthrough:

Blogging database

This tutorial uses a Blogging database on your LocalDb instance as the existing database.

Note

If you have already created the Blogging database as part of another tutorial, you can skip these steps.

  • Tools ‣ Connect to Database...
  • Select Microsoft SQL Server and click Continue
  • Enter (localdb)\mssqllocaldb as the Server Name
  • Enter master as the Database Name
  • The master database is now displayed under Data Connections in Server Explorer
  • Right-click on the database in Server Explorer and select New Query
  • Copy the script, listed below, into the query editor
  • Right-click on the query editor and select Execute
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
CREATE DATABASE [Blogging]
GO

USE [Blogging]
GO

CREATE TABLE [Blog] (
    [BlogId] int NOT NULL IDENTITY,
    [Url] nvarchar(max) NOT NULL,
    CONSTRAINT [PK_Blog] PRIMARY KEY ([BlogId])
);
GO

CREATE TABLE [Post] (
    [PostId] int NOT NULL IDENTITY,
    [BlogId] int NOT NULL,
    [Content] nvarchar(max),
    [Title] nvarchar(max),
    CONSTRAINT [PK_Post] PRIMARY KEY ([PostId]),
    CONSTRAINT [FK_Post_Blog_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blog] ([BlogId]) ON DELETE CASCADE
);
GO

INSERT INTO [Blog] (Url) VALUES 
('http://blogs.msdn.com/dotnet'), 
('http://blogs.msdn.com/webdev'), 
('http://blogs.msdn.com/visualstudio')
GO

Create a new project

  • Open Visual Studio 2015
  • File ‣ New ‣ Project...
  • From the left menu select Templates ‣ Visual C# ‣ Web
  • Select the ASP.NET Web Application project template
  • Ensure you are targeting .NET 4.5.1 or later
  • Enter EFGetStarted.AspNet5.ExistingDb as the name and click OK
  • Wait for the New ASP.NET Project dialog to appear
  • Under ASP.NET 5 Preview Templates select Web Application
  • Ensure that Authentication is set to No Authentication
  • Click OK

Install Entity Framework

To use EF7 you install the package for the database provider(s) you want to target. This walkthrough uses SQL Server. For a list of available providers see Database Providers.

  • Tools ‣ NuGet Package Manager ‣ Package Manager Console
  • Run Install-Package EntityFramework.MicrosoftSqlServer –Pre

Note

In ASP.NET 5 projects the Install-Package will complete quickly and the package installation will occur in the background. You will see (Restoring...) appear next to References in Solution Explorer while the install occurs.

To enable reverse engineering from an existing database we need to install a couple of other packages too.

  • Run Install-Package EntityFramework.Commands –Pre
  • Run Install-Package EntityFramework.MicrosoftSqlServer.Design –Pre
  • Open project.json
  • Locate the commands section and add the ef command as shown below
1
2
3
4
  "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel",
    "ef": "EntityFramework.Commands"
  },

Reverse engineer your model

Caution

The reverse engineer experience in ASP.NET 5 is still a work-in-progress. The following steps are overly complex and will be simplified by the time we reach a stable release.

Now it’s time to create the EF model based on your existing database.

  • Open a command prompt (Windows Key + R, type cmd, click OK)
  • Use the cd command to navigate to the project directory
  • Run dnvm use 1.0.0-rc1-update1
  • Run the following command to create a model from the existing database
dnx ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" EntityFramework.MicrosoftSqlServer --outputDir Models

The reverse engineer process created entity classes and a derived context based on the schema of the existing database. These classes were created in a Models folder in your project.

Entity Classes

The entity classes are simple C# objects that represent the data you will be querying and saving.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using System;
using System.Collections.Generic;

namespace EFGetStarted.AspNet5.ExistingDb.Models
{
    public partial class Blog
    {
        public Blog()
        {
            Post = new HashSet<Post>();
        }

        public int BlogId { get; set; }
        public string Url { get; set; }

        public virtual ICollection<Post> Post { get; set; }
    }
}

Derived Context

The context represents a session with the database and allows you to query and save instances of the entity classes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Metadata;

namespace EFGetStarted.AspNet5.ExistingDb.Models
{
    public partial class BloggingContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder options)
        {
            options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>(entity =>
            {
                entity.Property(e => e.Url).IsRequired();
            });

            modelBuilder.Entity<Post>(entity =>
            {
                entity.HasOne(d => d.Blog).WithMany(p => p.Post).HasForeignKey(d => d.BlogId);
            });
        }

        public virtual DbSet<Blog> Blog { get; set; }
        public virtual DbSet<Post> Post { get; set; }
    }
}

Register your context with dependency injection

The concept of dependency injection is central to ASP.NET 5. Services (such as BloggingContext) are registered with dependency injection during application startup. Components that require these services (such as your MVC controllers) are then provided these services via constructor parameters or properties. For more information on dependency injection see the Dependency Injection article on the ASP.NET site.

Remove inline context configuration

In ASP.NET 5, configuration is generally performed in Startup.cs. To conform to this pattern, we will move configuration of the database provider to Startup.cs.

  • Open ModelsBlogginContext.cs
  • Delete the lines of code highligted below
1
2
3
4
5
6
7
8
    public partial class BloggingContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder options)
        {
            options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)

Register and configure your context in Startup.cs

In order for our MVC controllers to make use of BloggingContext we are going to register it as a service.

  • Open Startup.cs
  • Add the following using statements at the start of the file
1
2
using EFGetStarted.AspNet5.ExistingDb.Models;
using Microsoft.Data.Entity;

Now we can use the AddDbContext method to register it as a service.

  • Locate the ConfigureServices method
  • Add the lines that are highlighted in the following code
1
2
3
4
5
6
7
8
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var connection = @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;";

            services.AddEntityFramework()
                .AddSqlServer()
                .AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));

Create a controller

Next, we’ll add an MVC controller that will use EF to query and save data.

  • Right-click on the Controllers folder in Solution Explorer and select Add ‣ New Item...
  • From the left menu select Installed ‣ Server-side
  • Select the Class item template
  • Enter BlogsController.cs as the name and click OK
  • Replace the contents of the file with the following code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using EFGetStarted.AspNet5.ExistingDb.Models;
using Microsoft.AspNet.Mvc;
using System.Linq;

namespace EFGetStarted.AspNet5.ExistingDb.Controllers
{
    public class BlogsController : Controller
    {
        private BloggingContext _context;

        public BlogsController(BloggingContext context)
        {
            _context = context;
        }

        public IActionResult Index()
        {
            return View(_context.Blog.ToList());
        }

        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Blog blog)
        {
            if (ModelState.IsValid)
            {
                _context.Blog.Add(blog);
                _context.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(blog);
        }

    }
}

You’ll notice that the controller takes a BloggingContext as a constructor parameter. ASP.NET dependency injection will take care of passing an instance of BloggingContext into your controller.

The controller contains an Index action, which displays all blogs in the database, and a Create action, which inserts a new blogs into the database.

Create views

Now that we have a controller it’s time to add the views that will make up the user interface.

We’ll start with the view for our Index action, that displays all blogs.

  • Right-click on the Views folder in Solution Explorer and select Add ‣ New Folder
  • Enter Blogs as the name of the folder
  • Right-click on the Blogs folder and select Add ‣ New Item...
  • From the left menu select Installed ‣ Server-side
  • Select the MVC View Page item template
  • Enter Index.cshtml as the name and click OK
  • Replace the contents of the file with the following code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@model IEnumerable<EFGetStarted.AspNet5.ExistingDb.Models.Blog>

@{
    ViewBag.Title = "Blogs";
}

<h2>Blogs</h2>

<p>
    <a asp-controller="Blogs" asp-action="Create">Create New</a>
</p>

<table class="table">
    <tr>
        <th>Id</th>
        <th>Url</th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.BlogId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Url)
            </td>
        </tr>
    }
</table>

We’ll also add a view for the Create action, which allows the user to enter details for a new blog.

  • Right-click on the Blogs folder and select Add ‣ New Item...
  • From the left menu select Installed ‣ ASP.NET 5
  • Select the MVC View Page item template
  • Enter Create.cshtml as the name and click OK
  • Replace the contents of the file with the following code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@model EFGetStarted.AspNet5.ExistingDb.Models.Blog

@{
    ViewBag.Title = "New Blog";
}

<h2>@ViewData["Title"]</h2>

<form asp-controller="Blogs" asp-action="Create" method="post" class="form-horizontal" role="form">
    <div class="form-horizontal">
        <div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Url" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Url" class="form-control" />
                <span asp-validation-for="Url" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
</form>

Run the application

You can now run the application to see it in action.

  • Debug ‣ Start Without Debugging
  • The application will build and open in a web browser
  • Navigate to /Blogs
  • Click Create New
  • Enter a Url for the new blog and click Create
../../_images/create.png ../../_images/index-existing-db.png