Using EntityFramework 6 Part 2: Database Connections

This post is part of a mini series on using EntityFramework (EF). If you do not have EF installed go to Part 1: Introduction and Setup to see what (basic) steps we took to get EF installed.
In this part we are going to use Code-First methods to start model building, then eventually connecting to the database . This is not the only way and you do not have to do things in exactly the same order as I have but if you follow along you should have a working version at the end.

Database
Firstly, create a database at your preferred location. Once you have a database add the connection string to the web.config file. I added a database to the App_Data folder so this is what the connectionsString definition look like in my web.config file.

  <connectionStrings>
    <add name="DBConn" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DB.mdf;Integrated Security=True"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

Next, add a class which inherits from DBContext. An instance of DBContext, LibraryDBContext in this example, is used to perform CRUD operations against a database. To read up on DBContext see these articles
http://www.entityframeworktutorial.net/EntityFramework4.3/dbcontext-vs-objectcontext.aspx

namespace WebApplication2.Models
{
    public class LibraryDBContext:DbContext
    {
        public LibraryDBContext() : base("DBConn")
        { }

        public DbSet<Book>Books{ get; set; }
    }
}

This gives sufficient Entity Framework code to enable our application to access a database.

The Model
Now we will start the model by creating a Book entity. Create a Book class in the Models folder of your application.

namespace WebApplication2.Models
{
    public class Book
    {
        public int BookId { get; set; }
        public string Author { get; set; }
        public string Title { get; set; }
    }
}

Following Code-First conventions, because we have defined an property called BookId (class name ‘Book’ plus ‘Id’) Entity Framework will nominate this property as an identity column when the database tables are generated. If we had a property simply named Id, Entity Framework would have nominated that as the identity and created an identity column called Id.

Displaying Book Info
Add a Controller to the application, I have called it BooksController. The Index action retrieves all the books from what will be the Books table.

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using WebApplication2.Models;

namespace WebApplication2.Controllers
{
    public class BooksController : Controller
    {
          public ActionResult Index()
        {
            var books = new List<Book>();
            using (var db = new LibraryDBContext())
            {
                books = db.Books.ToList();
            }
            return View(books);
        }
    }
}

The last code related change is to create a View for the Index Action to display all the books.

@model IEnumerable<WebApplication2.Models.Book>
    @Html.ActionLink("Create New", "Create")
<table class="table">
<tr>
<th>
            @Html.DisplayNameFor(model => model.Author)</th>
<th>
            @Html.DisplayNameFor(model => model.Title)</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
            @Html.DisplayFor(modelItem => item.Author)</td>
<td>
            @Html.DisplayFor(modelItem => item.Title)</td>
<td>
            @Html.ActionLink("Edit", "Edit", new { id=item.BookId }) |
            @Html.ActionLink("Details", "Details", new { id=item.BookId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.BookId })</td>
</tr>
}</table>

Running the Application
The application should build at this point. Currently we have a database that contains no tables. If you run the application now The database/tables will only be created/modified on a read/write action. So run the application and navigate to your controller (e.g. \books). Because the Index action of the Books controller contains code that retrieves data via the inherited DBContext class, and because Entity Framework knows there are models with no corresponding database table, the tables will be created with columns types that match the model properties.

Using EntityFramework 6 Part 1: Introduction and Setup

In this mini series we will be looking at how to implement EntityFramework 6 (from now on referred to as EF) into an MVC application, primarily using Code First methods. In this first part we are going to set up our project.  If you already have a project ready skip to the Setup EF section. If you already have EF version 6 installed feel free to go to part 2: Putting Database Connections into Context.

New MVC Project

I was going to lay out the steps required to create a new project. However, I assume you are able to complete that without step-by-step instructions. Depending on which options you select when creating a new project will determine whether you need to install EF. If you selected an internet application with individual user accounts then EF will have been installed during project creation with a DataContext used for user authentication.

Setup EntityFramework
There are two primary ways to install a NuGet package. By using PowerShell commands in the Package Manager Console or by using a visual interface.
To use the Package Manager Console go to Tools > Nuget Package Manager > Package Manager Console. At the NuGet command line enter this command to install EF

Install-Package EntityFramework -projectname DemoApplication

The -projectname switch forces EF to be installed in a specific project. If you have only one project in your solution you can omit the parameter and use

Install-Package EntityFramework

Either way you should see a message confirming EF has been successfully installed.

To use the visual interface go to Tools > NuGet Package Manager > Manage NuGet Packages for Solution… to open the interface.  On the left select Online and in the search box on the right enter entity framework.

nuget-entityframework6

I already have EF installed which is why you see a green circle with a tick.  If it is not installed then you will see an install button.
Once you have EF installed you are ready to continue.
 

Disabling the pluralization of table names when using database migrations

To disable the pluralizing of database names create a custom class that inherits from the DBContext class. In that class override the OnModelCreating method and call the Remove method of the dbModelBuilder.Conventions class as below.

using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace DemoApplication.Models
{
    public class EFDbContext : DbContext
    {
        //the base contains the name of the connection string provided in the web.config
        // this constructor should disable migrations
        public EFDbContext()
            : base("EFDbContext")
        {}

        protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
        {
            dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }

        public DbSet<Query> Query { get; set; }
    }
}

Disabling Entityframework Migrations

I have found a couple ways migrations can be turned off. The version of Entityframework you are using may determine which method you use.

The first method is to set the AutomaticMigrationsEnabled property to false in the DBMigrationsConfiguration class.

using System.Data.Entity.Migrations;
 
namespace DemoApplication.Migrations
{
    internal sealed class Configuration : DbMigrationsConfiguration<MyDBContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }
 
        protected override void Seed(MyDBContext context)
        {
            //  This method will be called after migrating to the latest version.
 
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}

The second method is to set a null Database Initializer in the constructor of the DBContext class. I have used this method in projects using Entityframework 6 where DBMigrationsConfiguration class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace DemoApplication.Models.Concrete
{
    public class EFDbContext : DbContext
    {
        //the base contains the name of the connection string provided in the web.config
        // this constructor should disable migrations
        public EFDbContext()
            : base("EFDbContext")
        {
            //disable initializer
            Database.SetInitializer<EFDbContext>(null);
        }

        public DbSet<Query> Query { get; set; }
    }
}

In any case, if there is a _MigrationHistory table in the database then delete it. This will be a user table in EF6. I believe it will show up as a system table in earlier versions of Entityframework.

As a last note. Some people have reported to have used disable-migrations in the Package Manager Console window. However when I have tried this in the past on EF6 it has not worked.

PM> disable-migrations
The term ‘disable-migrations’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify
that the path is correct and try again.
At line:1 char:19
+ disable-migrations <<<<
+ CategoryInfo : ObjectNotFound: (disable-migrations:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Adding Entityframework Data Access To A Project

Most new projects require some sort of data access method. I used the following steps with an MVC application in Visual Studio 2013, they should be enough to get you started. I am going to assume you have already have an MVC ready project open. To keep the code snippets short not all the namespace references are shown, just the key ones.

Setup the Database
It is up to you what type of database you use, SQLExpress, SQL Server or something else. Create a database and set the permissions as needed, most likely for development you will use integrated security.
For starters add a table to hold product data with the below script.

CREATE TABLE Products
(
    [ProductID] INT NOT NULL PRIMARY KEY IDENTITY,
    [ProductCode] NVARCHAR(100) NOT NULL,
    [Description] NVARCHAR(500) NOT NULL,
    [UnitPrice] DECIMAL(9, 2) NOT NULL
)

For now populate the table with some dummy data.

INSERT INTO Product ([ProductCode],[Description],[UnitPrice]) VALUES ('P1234', 'Torch', 23.99)
INSERT INTO Product ([ProductCode],[Description],[UnitPrice]) VALUES ('P3456', 'Toaster', 15.90)
INSERT INTO Product ([ProductCode],[Description],[UnitPrice]) VALUES ('P7890', 'Football', 10.00)
INSERT INTO Product ([ProductCode],[Description],[UnitPrice]) VALUES ('P1037', 'Hair Net', 3.50)
INSERT INTO Product ([ProductCode],[Description],[UnitPrice]) VALUES ('P1634', 'Cooker', 156.99)

Creating a table in the database is actually optional, if you go full Code-First and don’t create a table it will be created automatically by the DBInitializer on the first call requiring the table when the application is run. Just be aware that there will not be any data in the table initially.

Setup EntityFramework
Open the Package Manager Console by going to Tools > Nuget Package Manager > Package Manager Console. At the NuGet command line enter this command to install EntityFramework

Install-Package EntityFramework -projectname DemoApplication

the -projectname switch forces EntityFramework to be installed in a specific project. If you have only one project in your solution you could use

Install-Package EntityFramework

Create a Domain Model

  • In your application right-click the Models folder and select Add > Class… (Ctrl+Shift+A).
  • In the Add New Item dialog, select Class from the template list and enter a suitable name for your class e.g. Product.cs
  • Select the Add button
  • Edit the class with the properties you need
    namespace DemoApplication.Models
    {
        public class Product
        {
            public int ProductID { get; set; }
            public string ProductCode { get; set; }
            public string Description { get; set; }
            public decimal UnitPrice { get; set; }
        }
    }
    

Create a DBContext Class

  • In your application right-click the Models folder and select Add > Class… (Ctrl+Shift+A).
  • In the Add New Item dialog, select Class from the template list and enter a suitable name for your DBContext class e.g. EFDBContext.cs
  • Select the Add button
  • Edit the class similar to this
    using System.Data.Entity;
    
    namespace DemoApplication.Models 
    {
        public class EFDbContext : DbContext 
        {
            public DbSet&lt;Product&gt; Products { get; set; }
        }
    }
    

    The name of the property Products is the name of the table Entityframework will access. The type specified in the DBSet is the object Entityframework will populate.

Add a Connectionstring to Config
The connection string will depend on which database you connected to. AS I was using SQL Server my connectoin string looks similar to this.

&lt;connectionStrings&gt;
    &lt;add name=&quot;EFDbContext&quot; connectionString=&quot;Data Source=SERVERNAME;Initial Catalog=DATABASENAME;Integrated Security=True&quot; providerName=&quot;System.Data.SqlClient&quot;/&gt;
&lt;/connectionStrings&gt;

Create a Repository

  • First of all an interface, In your application right-click the Models folder and select Add > New Item… (Ctrl+Shift+A).
  • In the Add New Item dialog, select Interface from the template list enter a suitable name for your repository interface e.g. IProductRepository.cs
  • Select the Add button
  • Edit the repository interface
    using SportsStore.Domain.Entities;
    namespace DemoApplication.Models
    {
        public interface IProductRepository
        {
            IEnumerable&lt;Product&gt; Products { get; }
        }
    }
    
  • Next, the concrete Repository class. In your application right-click the Models folder and select Add > New Item… (Ctrl+Shift+A).
  • In the Add New Item dialog, select Class from the template list enter a suitable name for your repository e.g. EFProductRepository.cs
  • Select the Add button
  • Edit the ProductRepository class as below
    using System.Collections.Generic;
    
    namespace DemoApplication.Models 
    {
        public class EFProductRepository : IProductRepository 
        {
            private EFDbContext context = new EFDbContext();
            public IEnumerable&lt;Product&gt; Products 
            {
                    get { return context.Products; }
            }
        }
    }
    

Controller Setup
In your controller, add a Product Repository

using DemoApplication.Models;

namespace DemoApplication.Controllers
{
    public class ProductController : Controller
    {
        private IProductRepository repository;

        public ProductController()
        {
            this.repository = new ProductRepository;
        }

        public ViewResult Index() 
        {
            return View(repository.Products);
        }      
    }
}

Controller Setup
The very last thing to do is set up the view to display a list of products.

@model IEnumerable&lt;DemoApplication.Models.Product&gt;
@{
 ViewBag.Title = &quot;Products&quot;;
}
&lt;table&gt;
@foreach (var product in Model) {
&lt;tr&gt;
&lt;td&gt;@product.ProductCode&lt;/td&gt;
&lt;td&gt;@product.Description&lt;/td&gt;
&lt;td&gt;@product.UnitPrice.ToString(&quot;c&quot;)&lt;/td&gt;
&lt;/tr&gt;
}&lt;/table&gt;

This is a bit of a whirlwind tour but hopefullly enough information to get a project going in accessing data with Entityframework.