Entity Framework Code First Development With WebMatrix

4.68 (25 votes)

The existing data access story for WebMatrix is the Database Helper. Microsoft's recommended data access technology going forward is the Entity Framework (EF). This article explores how to use the Code First capability offered by EF within an ASP.NET Web Pages application.

The database helper was introduced to provide an easy way for beginners to use SQL in their web pages. As such, it works well, but has its critics. Some of them resorted to developing their own data access libraries to be used instead (see Data Access Choices For WebMatrix). The Entity Framework, on the other hand, is a Microsoft technology. Specifically, it is an Object/Relational Mapping (ORM) tool. Most professional developers prefer to work with data as objects instead of using SQL to directly query databases. ORM tools take care of all the plumbing work required to get data from the database and to populate object properties, or to translate the value of object properties to SQL UPDATE and INSERT statements. For example, if you were working on an application that dealt with books, you would expect it to feature a Book object. That Book object would have a number of properties, such as a Title, an ISBN, perhaps, and an Author. These would be defined in the object's class definition, and they would map to tables and columns in a database somewhere. The Code First approach enables you to define your objects, and then get EF to create a suitable database for you. You can then query your objects in C# via Language Integrated Query (LINQ), which gets translated to SQL behind the scenes and executed against the database.

To get started, you need to download the Entity Framework package and include it in your web site. You can get this via the Package Manager. Make sure that Default - All is selected as the source, and search for "entityframework" (one word). The most recent version (4.1.10715.0) errored when I tried to install it, but the previous one (4.1.10331.0) works for this example just as fine.

It's time to consider the "object model". Since I have already introduced the notion of a Books application, that will do for this example. The object model will be a simple one - it will consist of a Book object or Entity, an Author entity and a Category entity, in keeping with the samples I have used before. An Author entity has the following properties:

  • AuthorId (int)
  • FirstName (string)
  • LastName (string)
  • Biography (string)

A Category is an even more simple object consisting of two properties:

  • CategoryId (int)
  • CategoryName (string)

Finally, a Book entity consists of the following properties:

  • BookId (int)
  • Title (string)
  • Description (string)
  • ISBN (string)
  • DatePublished (DateTime)
  • Author (Author)
  • Category (Category)

Entities can be properties of other entities as evidenced by the Author and Category properties of the Book entity.

These entities need to be defined formally as classes in C# so that the EF can understand them and knows what to do with them. To do this, you need to add the Class (C#) file type to your application, but first you need to add a new folder called App_Code to your web site. All class files must go into this folder so that they get compiled when your site first runs. Here is a simple class definition for the Author entity as Author.cs:

public class Author
    public int AuthorId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Biography { get; set; }

And further classes for the Category and Book entities:

public class Category
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }


public class Book
    public int BookId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string ISBN { get; set; }
    public DateTime DatePublished { get; set; }
    public Category Category { get; set; }
    public Author Author { get; set; }

These are fine as a basic class definitions, but they need some additional work done to them to make them suitable for Code First. By default, all strings are mapped to nvarchar(4000) data types. This is too large for most purposes and you would ideally want to constrain the size of a number of fields. Additionally, the Biography should map to an ntext field - not limited to 4000 characters. A one-to-many relationship needs to be defined between Authors and their Books, and between Categories and their Books. Here's how both issues are solved in code for the Author class:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public class Author
    public int AuthorId { get; set; }
    [MaxLength(35)] public string FirstName { get; set; }
    [MaxLength(35)] public string LastName { get; set; }
    [MaxLength] public string Biography { get; set; }
    public virtual ICollection<Book> Books { get; set; }

The bit in square brackets [ ] is an attribute. These come from System.ComponentModel.DataAnnotations which is why that namespace has been referenced with a using statement at the top of the class file. Data annotation attributes are used for providing metadata to the Entity Framework, and the MaxLength attribute will result in nvarchar columns being created with a limit of 35 characters for the first and last name. When you provide no limit, MaxLength translates to an ntext column - which is what is wanted for the Biography property. Finally, the Author is provided with an additional property - a collection of Book objects, hence the inclusion of the System.Collections.Generic namespace. The collection is marked as virtual, which ensures that EF lazy-loads the collection. In other words, books belonging to an author are only ever retrieved from the database when they are referenced in code, and not just because an Author object was instantiated. Following these changes, here are the revised definitions for the Category class and the Book class:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public class Category
    public int CategoryId { get; set; }
    [MaxLength(50)] public string CategoryName { get; set; }
    public virtual ICollection<Book> Books { get; set; }


using System;
using System.ComponentModel.DataAnnotations;

public class Book
    public int BookId { get; set; }
    [MaxLength(200)] public string Title { get; set; }
    [MaxLength] public string Description { get; set; }
    [MaxLength(20)] public string ISBN { get; set; }
    public DateTime DatePublished { get; set; }
    public int CategoryId { get; set; }
    public int AuthorId { get; set; }
    public virtual Category Category { get; set; }
    public virtual Author Author { get; set; }

The Book class includes a Category property and an Author property. These are marked as virtual as well, and will contain details of the related category and author. The relationship itself is formed via the AuthorId and CategoryId properties, which map back to the respective Category and Author objects.

A final class is needed. This class is responsible for managing communication between the entities and the database (once it has been generated). In EF parlance, the object that manages this is called a Context and it is represented by the DbContext class. You create your own Context class that inherits from DbContext. In the code below, you can see that I chose to name my Context as BookContext. It also includes a number of strongly typed DbSet properties. There is one for each entity, and they will map to tables in the database. Notice that they represent pluralised versions of the entities.

using System.Data.Entity;

public class BookContext : DbContext
    public DbSet<Book> Books { get; set; }
    public DbSet<Author> Authors { get; set; }
    public DbSet<Category> Categories { get; set; }

The final step at this stage is to tell the Context where the database should be. You do that by adding a connection string to the Web.Config file:

<?xml version="1.0"?>


        <compilation debug="false" targetFramework="4.0" />
        <add name="BookContext" connectionString="Data Source=|DataDirectory|Books.sdf" 
             providerName="System.Data.SqlServerCe.4.0" />

The name for the connection string entry is the same as the Context class - BookContext. That is the configuration required by EF Code First. Notice the use of the substitution string |DataDirectory| prior to the database file name - by default, this maps to the App_Data folder in an ASP.NET web site. You don't need any more at this stage. If you run the application - assuming you have a blank page to run - a SQL Compact 4.0 database will be created in the App_Data folder:

Notice that each of the DbSet objects is represented by a table, and see also that the Title for a Book is and nvarchar(200) column - as dictated by the DataAnnotation attribute that was placed on that property. There is also another table - EdmMetadata. This table provides a way for Code First to detect if any changes have occurred to the object model since the database was last generated. If the model changes, an exception is thrown when you next try to run the application. What you can do is to prevent the exception by adding the following to an _AppStart file:

@using EF = System.Data.Entity;
    EF.Database.SetInitializer(new EF.DropCreateDatabaseIfModelChanges<BookContext>());

There is a potential clash between the Database classes of System.Data.Entity Database and WebMatrix.Data. Therefore the Database class needs to be referenced by its fully qualified name. To save some typing, the namespace is referenced in a using statement via an alias (EF), which is used in its place. The effect this has is to delete the entire database, data and all, and recreate it silently according to the changed model definition - without data. There is an alternative approach which allows you to provide seed data in the event that the database is dropped and recreated.

All kind of cool and groovy - but what about getting data into the database and displaying it? The following code does exactly that:

    var db = new BookContext();
    var categories = new List<Category>{
        new Category{CategoryName = "WPF"},
        new Category{CategoryName = "JavaScript"},
        new Category{CategoryName = "ASP.NET"}
    foreach(var c in categories){
    var authors = new List<Author>{
        new Author{FirstName = "Mike", LastName = "Brind"},
        new Author{FirstName = "Imar", LastName = "Spaanjaars"}
    foreach(var a in authors){
    var book = new Book{
        Title = "Beginning ASP.NET Web Pages With WebMatrix",
        Description = "Buy this book!",
        ISBN = "978-1118050484",
        DatePublished = new DateTime(2011,10,18),
        AuthorId = 1,
        CategoryId = 3
    categories = db.Categories.OrderBy(c => c.CategoryName).ToList();
    authors = db.Authors.OrderByDescending(a => a.FirstName).ToList();
    book = db.Books.FirstOrDefault();
<!DOCTYPE html>

<html lang="en">
        <meta charset="utf-8" />
        @foreach(var c in categories){
            @c.CategoryName<br />
        @foreach(var a in authors){
            @a.FirstName @a.LastName<br />
        Description: @book.Description<br />
        ISBN: @book.ISBN<br />
        Publication Date: @book.DatePublished.ToLongDateString()<br />
        Author: @book.Author.FirstName @book.Author.LastName<br />
        Category: @book.Category.CategoryName

Here's a view of the output from running this page:

All communication with the database is done via the DbContext object. New entity instances are attached to the relevant DbSet property, and then the DbContext.SaveChanges method is called, which causes the required SQL to be generated and executed against the database. Retrieving data from the database is also conducted via the DbContext object using LINQ to Entities. Multiple items are transferred to a List<T>, whereas singular items are obtained using the SingleOrDefault() extension method.

What are the benefits of this approach over, say, the Database Helper in WebMatrix 1.0? Probably none, as it stands. However, if you work with Web Pages via Visual Web Developer 2010 SP1, or Visual Studio 2010 SP1, you immediately benefit from strong typing. Object properties are provided through Intellisense:

This gives you compile-time checking which you simply do not enjoy from dynamic types. WebMatrix v 2.0 will include full Intellisense. That will make the Code First story a lot more compelling. Entity Framework is the recommended approach to data access according to Microsoft, which means that development effort will be put behind the framework. It supports the object-oriented approach to working with data that professional developers use, and is not too high in concept counts at a basic level.

A sample site to accompany this article is available at Github. The database will be created the first time you run the site.


Date Posted:
Last Updated:
Posted by:
Total Views to date: 37282


- Robby

Great stuff. It would really be nice if you had a companion article that illustrated DB-first use of EF in WebMatrix.

Also, hope your new book will come out in Kindle, too. When I am on the road, Kindle is my friend.

- hajan

Great post!

- Mike


The DB-first approach works well when using VWD/VS, because they have the design tools and code generation templates etc. WebMatrix doesn't have those tools. I doubt if it ever will.

- Ali

Great post: clever, clear and concise :)

- reav

oh yeah, and with webmatrix 2 it goes so well!

- dc

Do you see any performance hits using codefirst? I've tried code first and it seems to be much slower than any other data access I've used. Especially compared to WebPage's database helper which seems really speedy.

Locally my sites using code first are fine, but when I put them up on hosts they slow down a lot. Many times it takes several times longer for a page to appear versus the same functionality using the database helper. I understand the first hit will be slower due to compiling, but every hit is slower than what I'd consider normal. I was thinking my code first seems either "heavy" or like it's trying to do something and then gives up.

- Markus Strauss

great article!

but i have the problem that i get the following error when running the web app:

CS0234: Der Typ- oder Namespacename "Entity" ist im Namespace "System.Data" nicht vorhanden. (Fehlt ein Assemblyverweis?)

Translation: The type or namespace "Entity" was not found in "System.Data" (Missing assembly reference?)

- Mike


Make sure that the EntityFramework.dll file is in your bin folder. IF you downloaded EF via the Package Manager as described at the top of the article, this should have happened.

- Patrick K Tshiuma

I just read this article and I can say it's very helpful since I am still learning how to use razor and webmatrix.

I also have a question:

Does the EntityFramework.dll has to be downloaded for every web application that I'd like to develop with web matrix or is it like VS where I can add reference whenever I need.?

Thanks a lot.

- Mike


WebMatrix doesn't offer a way to add a reference, so you need to download the package. That might change with the next version though. Then again, it might not.

- Sulekh Verma


Recent Comments

Thomas 05/03/2018 00:59
In response to I'm Not Writing A Book On Razor Pages
There's a typo on this page: = true)] should be [BindProperty(SupportsGet = true)]...

Rolf Herbert 04/03/2018 19:25
In response to I'm Not Writing A Book On Razor Pages
So is MS deprecating razor Web Pages..? Is it dead..? I wish they would stop killing things so its...

Borut 17/02/2018 12:59
In response to I'm Not Writing A Book On Razor Pages
Mike, is it possible that Web Pages and Razor Pages "live" together in one web application? I a I...

hrboyce 09/02/2018 04:44
In response to I'm Not Writing A Book On Razor Pages
Mike, First thanks for doing this but I have to ask, any chance you would consider converting one of...

aziz sallam 07/02/2018 10:18
In response to I'm Not Writing A Book On Razor Pages
u are a great man...

Satyabrata Mohapatra 31/01/2018 11:36
In response to I'm Not Writing A Book On Razor Pages
This is a great news!!!! Thanks...

tangdf 30/01/2018 07:25
In response to I'm Not Writing A Book On Razor Pages
=> { o.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute()); }); The extension method does...

Obinna Okafor 30/01/2018 04:02
In response to I'm Not Writing A Book On Razor Pages
Thank you very much. I would like to see a project built from scratch using Razor Pages. And it show...

rachida Dukes 31/10/2017 13:52
In response to Customising Identity in Razor Pages
Thanks again for this wonderful tutorial. I followed all the steps in this section called: Adding...

Rachida 31/10/2017 12:06
In response to Customising Identity in Razor Pages
Thanks very much for this wonderful tutorial, it helped a lot....