Asp.Net MvC 3 from scratch: Models

This is the third article in the series where we create a book review application from scratch using Asp.Net MvC 3. In this article were going to start developing the data layer for our application. Since this goal is fairly large I will be chopping it up into three articles, this article will get our data layer up and running. The upcoming two articles will cover unit-testing and proper integration with the rest of the application through dependency injection.

The data layer

The main concern of the data layer is to manage and persist the data of the application. We will build our data layer using the Entity Framework 4.0, a object relational mapper tool build by Microsoft. The newest version of the framework offers a lot of neat new features, the most prominent being the “code first approach”. This feature allows us build our data layer starting with hand coding the data classes (the models). The database will be generated later using the models as the blueprint. The benefits of this approach: the models are clean, not generated by any tool and not directly coupled to Entity Framework. To utilize this approach we have to install an extension for the Entity Framework called “EFCodeFirst”, which you can install through the NuGet Package manager.

The basics

Before we get started, the data layer can be created inside a separate project in our solution, this makes it easier to physically recognize the existence of a separated layer and it dividing the application into multiple projects helps with structuring as the application grows larger. All right then let’s get started with coding our models. I will start with coding the basic models we need at this point, the book and the review:

public class Book
{
        public int Id {get; set; }
        public string Name { get; set; }
        public string Author { get; set; }
        public string ISBN { get; set; }
}

public class Review
{
        public int Id { get; set; }
        public Book Book { get; set; }
        public string Content { get; set; }
        public DateTime Created { get; set; }
}

Now we that we got our basic models in place we have to make the Entity Framework aware of their existence. The code first way to do this is to define a context that derives from the DbContext. The models themselves live inside the context as DbSets:

public class EntityContext : DbContext
{
        public DbSet<Review> Reviews { get; set; }
        public DbSet<Book> Books { get; set; }
}

As mentioned before the database is generated using the model as the blueprint. Personally i like to start with standard set of dummy data every time i run my application. The database if recreated by the Entity Framework every time i run my application, then the dummy data is inserted. We have to code the dummy data so the example provided here is pretty basic:

public class EntityBaseData : DropCreateDatabaseAlways<EntityContext>
{
        protected override void Seed(EntityContext context)
        {
            context.Books.Add(new Book{Author = "Oskar uit de Bos", ISBN = "1234567", Name = "Book1"});
        }
}

Notice that our class inherits from a class class DropCreateDatabaseAlways, which tells the Entity Framework to drop and recreate a fresh database. Insert the class into the gloabal.asax like this:

protected void Application_Start()
{
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            DbDatabase.SetInitializer(new EntityBaseData());
}

Last step is setting up the connection to the database. By default the Entity Framework looks for a connection string with a name that matches our custom DbContext name, in our case EntityContext. Lets give the Entity Framework what it wants, add the following connection string to the web.config file:

<connectionStrings>
    <add name="EntityContext"
         connectionString="data source=.\SQLEXPRESS;Database=BookReviews5;Integrated Security=SSPI;"
         providerName="System.Data.SqlClient" />
</connectionStrings>

The next step

While we got our basic setup covered there is little to no structure at this point, so let’s apply some structure. Most of you should be familiar with the concept of repositories, they encapsulate the mechanisms for storing, retrieving and querying data from the rest of the application. Repositories act as gateways and guardians for our data, preventing data access logic from being scattered all over our data layer. Now that we got some basic structure in place we got testability to think about. While there are many different approaches for testing a data layer, i will take a strict unit-testing approach, so not integration testing with the database.

The focus of the unit-testing lies with data access logic inside the repositories. To enable testing without the database we will abstract the link to the database (our custom DbContext) away from the repositories into a separate component. Let’s start with this separate component, since we will need it when we start working on our repositories.

I named this component EntityProvider, since its main function is to provide the application’s data (entities) to our repositories. The basic idea is that every version of the EntityProvider exposes data through several IDbSet interfaces. The first implementation, our main implementation, works with the actual database. The implementation looks like this:

public interface IEntityProvider
{
        IDbSet<Review> Reviews { get; set; }
        IDbSet<Book> Books { get; set; }

        void PersistChanges();
}

public class SqlEntityProvider : IEntityProvider
{
        private readonly DbContext _context;

        public SqlEntityProvider()
        {
            _context = new EntityContext();
        }

        public IDbSet<Review> Reviews
        {
            get { return _context.Set<Review>(); }
            set { Reviews = value; }
        }

        public IDbSet<Book> Books
        {
            get { return _context.Set<Book>(); }
            set { Books = value; }
        }

        public void PersistChanges()
        {
            _context.SaveChanges();
        }
}

Now on to the first repository. As mentioned before, repositories act as gateways and guardians for our data.  Since there is a basic set of functionality that every repository should have, i have created a simple interface. The first implementation, our book repository, will only implement basic functionality by the interface. Our first repository looks like this:

public interface IRepository<T> where T : class
{
        IEnumerable<T> All();

        void Change(int id, T entity);
        void Add(T entity);
        void Remove(T entity);
}

public class BookRepository : IRepository<Book>
{
        private IEntityProvider Provider { get; set; }

        public BookRepository(IEntityProvider provider)
        {
            Provider = provider;
        }

        public IEnumerable<Book> All()
        {
            return Provider.Books.AsEnumerable();
        }

        public void Change(int id, Book entity)
        {
            Book item = Provider.Books.Where(e=>e.Id == id).FirstOrDefault();
            item.Name = entity.Name;
            item.ISBN = entity.ISBN;
            item.Author = entity.Author;

            Provider.PersistChanges();
        }

        public void Add(Book entity)
        {
            Provider.Books.Add(entity);
            Provider.PersistChanges();
        }

        public void Remove(Book entity)
        {
            Provider.Books.Remove(entity);
            Provider.PersistChanges();
        }
}

Wrapping up

We got a lot of work done, it’s time to wrap up the first article on the models. We have created basic models and wired them up to the Entity Framework using the code first approach. For more in-depth information on the code first approach check out this resource.  We created our first testable repository which contains basic functionality. But how about some results for all our hard work? A possible quick test is adding the following code to the index action of the home controller.

public ActionResult Index()
{
            SqlEntityProvider provider = new SqlEntityProvider();
            BookRepository repository = new BookRepository(provider);
            var result = repository.All();

            ViewBag.Message = result.FirstOrDefault().Author;

            return View();
}

Note that is not the proper way of integrating the repositories with the controllers, this is simply for the quick and dirty results. The proper loosely coupled way to integrate these components is through dependency injection, will will be covered in a later article. I expect the next article to be up within a week or so, until then happy coding. Feel free to ask questions, feedback is much appreciated. Full source for all that we have done so far is available here.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>