Introduction
In my previous article I
discussed developing a simple, multi-layered architecture for a .NET
application. However, there were few points that I skipped considering that the
article was for beginners. When we talk about an application architecture there
are certain points that need to be put into consideration before initiating. For example:
- Is
the architecture loosely coupled?
- Is it
to be service based?
- Where
should the entities reside?
- What
should be Mode of Communication with the database?
- Do it
require design patterns? If yes,What patterns should be implemented?
- Should
it be based on Separation of Concerns?
To answer these type of questions, .NET 4 has come up with a generic
solution, making use of Entity Framework.
My effort in this article was to put some light on building a generic
multilayered architecture using Entity Framework 4.1 and MVC3 razor view
engine. We'll use inversion of control to resolve dependency of layers. The
points to be covered in this article would be as follows:
- Use
of Seperation of Concerns,
- Use
of Code First approach,
- POCO
objects,
- Repository
Pattern,
- Dependency
Injection and Inversion of Control.
Architecture
Overview
I have created an architecture to
explaining all the above mentioned points, and we'll stick to this architecture
until the end of article, thus implementing practically our understanding.
I
have created a very simple application to add student details in a database. To
edit it and to delete it, my first page shows a list of all added students.
The architecture is service based. The following are the components and pictorial
representation (fig1) of it, we'll discuss each component in detail.
- CodeFirstData
layer.
- CodeFirstEntities
layer.
- CodeFirstServices
layer.
- MVC
Portal layer.
(fig 1.)
Architecture
components
Let's discuss each and
every component of the defined architecture in detail,
1. CodeFirstData layer
The data layer is the class library defining a layer which is responsible for
interacting with database, contains context classes and a factory pattern
implementation to interact with database. The layer contains the repository for
each entity to map with database, thus making a complete ORM (Object Resource
Model) solution. The class library references EntityFramework DLL to implement
the dbcontext classes.
2.
CodeFirstEntities
layer
Entity layer acts as a model to MVC application, and is also responsible for the
creation of DataBase objects when the dbset is first executed. It contains
Entity classes in POCO form, having relations and data annotations(Rules/Constraints to be put on Database table/columns).
The
properties of the class results in column name in database and name of the
class in Database table. The primary key is either defined by the property named Id
or "Classname[Id]
". In our case it is "StudentId
" and this is the default protocol set by
the entity framework to keep in mind while creating entities. Since this application
is code first, we need to create entities first.
3. CodeFirstServices
layer
The layer contains services which uses repositories to fetch data from
database. The interaction between Services and Repositories is kept loosely
coupled thus implementing Inversion of Control using Dependency Injection. It is
constructor based dependency injection and does not allow service to make a direct
instance of our repositories. Service layer acts as an interface between
controllers and repositories, and passes the requests of a controller to repositories.
4.
MVCPortal
layer
MVCPortal layer is our UI layer, it contains Model/ViewModels, Views and
Controllers. I am not going into details of MVC as it is not our primary target. I
assume that you already know how to create and run an MVC application. Let's have do
quick revision of MVC.
i. Model / Viewmodel
Model class are responsible for holding up and manipulating data, we bind
model/viewmodel classes to views to display model specific data.model classes, which are prepopulated by controllers to show data with the lehp of views.
ii. Views
Views holds up our UI templates. We have controller methods defined for every
view, which populates View Design with data, and requests particular type of
view to be rendered at user's end as per requirement.
iii. Controllers
Web-based MVC frameworks map URLs to server code in a bit
of a different fashion. Instead of mapping incoming URLs to HTML/aspx files, they
instead map URLs to methods on classes. These classes are called
"Controllers" and they are responsible for processing incoming HTTP
requests, handling user input, retrieving and saving data, and determining the
response to send back to the client (display HTML, download a file, redirect to
a different URL, etc.).
The layer makes use of Dependency injection to
achieve Inversion of Control for services, thus not allowing controllers to
directly acces services instances. The IOC is acheived using global.asax file
using UnityFramework library of Microsoft.
5. Dlls
I have created the DLLs folder and given the output build path for
every class library to that folder, for ease of access to DLL's to add
reference. Now each DLL will be created in the DLLs folder and we can access the
desired DLL from the same folder. Also keep the
EntityFramework, UnityConfiguration DLLs into it.
IOC and DI
Dependency
Injection is an important component in my application. All the services are
required to be late bound with Model layer with Dependency Injection. In
addition, the IoC container manages the lifetime of service objects. For
example, the Context object. I set lifetime
type as PerThreadLifetimeManager
in Unity configuration.
This makes one and only one context object created in a single request and the
different request has a different context object.
Another thing I want to mention is ASP.NET MVC3 has its own way to provide
Dependency Inject for controller via implementing DependencyResolver interface. The IoC
container I used in the demo is Unity.
Container
The
"Container" or "IOC Container" is the main object that is
used to create objects and inject dependencies into them. Whenever you want an
object to be open to IoC, you have to use the container to create the instance
using container.Resolve<T>()
method instead of the "new"
keyword.
IService service = unityContainer.Resolve< Iservice>();
I have added following references to
acheive the same,
Microsoft.Practices.Unity
Microsoft.Practices.Unity.Configuration
The code for IOC is
implemented in global.asax file.
Step by Step Process to
create the Application using EntityFramework Architecture :
Application Overview
We'll try to develop a simple studentDetails
application with the help of
discusses architecture. The application's main module will be to Create a new
student, Edit an existing student, Delete an existing student, and to show a list of all
students. Looking into a wider/generic perspective, the application performs
CRUD operations on database with the help of EF .
Note that we'll not
create databse by our own, we just write classes and defing connection
configuration of our database server in the web.config file, and let
EntityFramework do rest of the job of creating database, managing database and
Mapping database with our entities.
Step1. Creating
a solution and blank projects/seperating them logically/physically as layers
Our first
initiative is to prepare our initial level architecture there by creating
solution and adding project files to it. We create a solution named
CodeFirstEntities and add three class libraries to it thus defining our three
layers which are Entity, Data and Service. The names of the class libraries
which I chose are CodeFirstEntities
, CodeFirstData
and CodeFirstServices
respectively.
Now add an MVC3
application to the solution called MvcPortal, that will act as a UI layer for
our application. Refer fig2 for implementing the first step.
( fig2 )
Step 2. Creating
Entities
Add Student.cs class to CodeFirstEntities project. This class
will contain the student details specific properties that will take the shape
of database table and columns. The class makes use of DataAnnotation DLL to
put data annotations (rules/constraints) over the properties that will be
reflected in database table. The constraints (like max length and required
parameter) are provided as attributes over the properties of the class as shown
in fig3 and fig4.
( fig3 )
( fig4 )
The
above entities is very simple POCO (Plain Old CLR Object) class and the entity
Student is decorated with validation attributes in the
System.ComponentModel.DataAnnotations
namespace. Now we want to use these
entities for defining model objects for the Entity Framework 4. Using the Code
First approach of Entity Framework, we can first define the entities by simply
writing POCO classes without any coupling with any API or database library.
This approach lets you focus on domain model which will enable Domain-Driven
Development for applications. EF code first support is currently enabled with a
separate API that is runs on top of the Entity Framework 4.
Step
3. Creating Repositories/Contexts
Our next step is to create the
contexts/repositories for our application and classes that will interact with
the database.
A. Create Context Class for Entity Framework
We have already prepared our domain model now let’s create a class
in order to working with Entity Framework Code First. I have added reference to
EntitFramework.dll CTP 4.1 to this class library project. We create two folders
DBInteractions and EntityRepositories to segregate our classes as in fig5. We'll come to that later, first let me explain the context class.
(fig 5)
(fig 6)
The above
class CodeFirstContext
in fig 6 is derived from DbContext that can connect your
model classes to a database. The CodeFirstContext
class is mapping our Student
class to database
tables Student use DbSet<TEntity>
where TEntity
is any POCO class. When
we are running the application the first time, it will automatically create the
database. EF code-first look for a connection string in web.config or
app.config that has the same name as the dbcontext class. If it does not find any
connection string with the convention, it will automatically create database in
local SQL Express database by default and the name of the database will be same
name as the dbcontext class. You can also define the name of database in
constructor of the the dbcontext class. The model classes of Code First are
working on the basis of conventions and we can also use a fluent API to refine
our model. The convention for primary key is ‘Id
’ or ‘<classname>Id
’ as I
discussed before. If the primary key properties are detected with the type ‘int
’,
‘long
’ or ‘short
’, they will automatically be registered as identity columns in
the database by default. Primary key detection is not case sensitive. We can
define our model classes with validation attributes in the System.ComponentModel.DataAnnotations
namespace and it automatically enforces validation rules when a model object is
updated or saved.
I ) DBInteractions
B. Generic
Repository for EntityFramework Code First
We have now
created model class and dbcontext class. Now we create a generic repository
pattern for data persistence with EF code first. Let’s create a generic
repository to working with DbContext and DbSet as follows. The following
classes will be added to DBInteractions folder for ease of understanding logic.
(fig 7)
C. DataBase Factory
We have our
database factory class defined as follows,
(fig 8)
(fig 9)
Where
IDBFactory
is the interface implemented by our factory class DBFactory. The
factory class is inherited from Disposable
class as shown below in fig
10 and is responsible for releasing disposing database resources.
(fig 10)
D. RepositoryBase – The Generic Entity Repository base class
The above is the
repository base class that contains all the methods to be implemented for CRUD
DB operations. We can define more of our generic methods here, for now
considering our application, these are eough for proper understanding of the
working.
E. Unit of Work
The Unit of Work pattern maintains a list
of objects affected by a business transaction and coordinates the writing out
of changes and the resolution of concurrency problems. We create a class for
handling Unit of Work pattern,
Interface
Class
The Commit
method written in of the UnitOfWork
will call the commit method of our Context
class and it will execute the SaveChanges
method of DbContext
class.
II ) Repository
In this
article, we will be primarily focus on the persistence against Student entity.
Let’s create a repository for handling CRUD operations for Student
using derive
from a generic Repository EntityRepositoryBase<T>.
Repository
class for Student
Interface
Class
Step 4. Creating a
Service Layer
Service Layer defines an
application's scope and its available set of operations from the perspective of
interfacing client layers. It encapsulates the application's business logic controlling transactions and
coordinating responses in the implementation of its operations. Controller
classes should be made light and do not put much of business logic onto it. We
can use the service layer as the business
logic layer and can encapsulate the rules of the application. We define interfaces and
corresponding student service for our application business logic. Since we are
targetting CRUD operations, so the methods are quite simple in implementation.
Interface
As we can see in abve interface the
methods are to Get Student Details, List, Update and Delete Student.
Class
using System.Collections.Generic;
using CodeFirstData.DBInteractions;
using CodeFirstData.EntityRepositories;
using CodeFirstEntities;
using CodeFirstServices.Interfaces;
namespace CodeFirstServices.Services
{
public class StudentService : IStudentService
{
private readonly IStudentRepository _studentRepository;
private readonly IUnitOfWork _unitOfWork;
public StudentService(IStudentRepository studentRepository, IUnitOfWork unitOfWork)
{
this._studentRepository = studentRepository;
this._unitOfWork = unitOfWork;
}
#region IStudentService Members
public IEnumerable<Student> GetStudents()
{
var students = _studentRepository.GetAll();
return students;
}
public Student GetStudentById(int id)
{
var student = _studentRepository.GetById(id);
return student;
}
public void CreateStudent(Student student)
{
_studentRepository.Add(student);
_unitOfWork.Commit();
}
public void DeleteStudent(int id)
{
var student = _studentRepository.GetById(id);
_studentRepository.Delete(student);
_unitOfWork.Commit();
}
public void UpdateStudent(Student student)
{
_studentRepository.Update(student);
_unitOfWork.Commit();
}
public void SaveStudent()
{
_unitOfWork.Commit();
}
#endregion
}
}
Class uses refernces of Repositories
and Entities, and Dependency of Repositories is resolved in Constructor of the
service itself.
Step 5. The MVC Portal
Before we start MVC
portal, let's clear our logic for IOC and DI.I since we have already discussed IOC in the
article. For resolving Dependency we create certain classes as discussed below,
to get independent service request, we also create a custom lifetime
manager for Unity to store container in the current HttpContext
.
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
{
public override object GetValue()
{
var assemblyQualifiedName = typeof (T).AssemblyQualifiedName;
if (assemblyQualifiedName != null)
return HttpContext.Current.Items[assemblyQualifiedName];
return null;
}
public override void RemoveValue()
{
var assemblyQualifiedName = typeof (T).AssemblyQualifiedName;
if (assemblyQualifiedName != null)
HttpContext.Current.Items.Remove(assemblyQualifiedName);
}
public override void SetValue(object newValue)
{
var assemblyQualifiedName = typeof (T).AssemblyQualifiedName;
if (assemblyQualifiedName != null)
HttpContext.Current.Items[assemblyQualifiedName] = newValue;
}
public void Dispose()
{
RemoveValue();
}
}
}
We create a dependency resolver for
resolving service dependency as follows.
ASP.NET MVC 3 has introduced a new
interface IControllerActivator
which lets you activate controllers with custom
behavior and can be use it for dependency injection purpose. The IControllerActivator
interface is
discoverable using the dependency resolver. Let’s create a custom controller
activator class by deriving from IControllerActivator
intreface.
using System;
using System.Web.Mvc;
namespace CodeFirstPortal.IoC
{
public class CustomControllerActivator : IControllerActivator
{
IController IControllerActivator.Create(
System.Web.Routing.RequestContext requestContext,
Type controllerType){
return DependencyResolver.Current
.GetService(controllerType) as IController;
}
}
}
We also create a UnityController
Factory and Configure contract and concrete types of unity in global.asax file.
ASP.NET MVC 3 has also introduced a
new interface IDependencyResolver
which exposes two methods - GetService
and
GetServices
. The GetService
method resolves singly registered services that support arbitrary object creation
and the GetServices
resolves multiply registered services. Implementations of
the IDependencyResolver
interface should delegate to the underlying dependency injection container to
provide the registered service for the requested type. When there are no
registered services of the requested type, the ASP.NET MVC framework expects implementations of this interface to
return null from GetService and to return an empty collection from GetServices
.
Let’s create a custom dependency resolver class by deriving from IDependencyResolver
intreface in
order to working with Unity to providing dependency injection.
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
namespace CodeFirstPortal.IoC
{
public class UnityControllerFactory : DefaultControllerFactory
{
IUnityContainer container;
public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
}
protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
{
IController controller;
if (controllerType == null)
throw new HttpException(
404, String.Format(
"The controller for '{0}' could not be found" + "or it does not implement IController.",
reqContext.HttpContext.Request.Path));
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(
string.Format(
"Requested type is not a controller: {0}",
controllerType.Name),
"controllerType");
try
{
controller= container.Resolve(controllerType) as IController;
}
catch (Exception ex)
{
throw new InvalidOperationException(String.Format(
"Error resolving the controller {0}",
controllerType.Name), ex);
}
return controller;
}
}
Resolving Service Dependency
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
namespace CodeFirstPortal.IoC
{
public class UnityDependencyResolver : IDependencyResolver
{
IUnityContainer container;
public UnityDependencyResolver(IUnityContainer container)
{
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch
{
return new List<object>();
}
}
}
}
global.asax
Add service
project reference, entity project reference and data project reference to the
portal.
The SetResolver
method of
DependencyResolver
class provides a registration point for dependency injection
containers. In this method, we configure the UnityDependencyResolver
class for providing dependency injection with
Unity 2.0. The SetResolver
method will be working with any dependency injection
container. If you want to use StructureMap
as the dependency injection container, you can create a dependency
resolver class in order to working with StructureMap
by deriving
IDependencyResolver
interface and later you can configure this class with
SetResolver
method. The ASP.NET MVC 3 is
providing a good support for working with dependency injection containers.
using System.Web.Mvc;
using System.Web.Routing;
using CodeFirstData.DBInteractions;
using CodeFirstData.EntityRepositories;
using CodeFirstPortal.IoC;
using CodeFirstServices.Interfaces;
using CodeFirstServices.Services;
using Microsoft.Practices.Unity;
namespace MvcPortal
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
IUnityContainer container = GetUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private IUnityContainer GetUnityContainer()
{
IUnityContainer container = new UnityContainer()
.RegisterType<IDBFactory, DBFactory>(new HttpContextLifetimeManager<IDBFactory>())
.RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>())
.RegisterType<IStudentService, StudentService>(new HttpContextLifetimeManager<IStudentService>())
.RegisterType<IStudentRepository, StudentRepository>(new HttpContextLifetimeManager<IStudentRepository>());
return container;
}
}
}
To start with MVC our first step is
to define our connection string as follows in the web.config file.
Steps to Create
Controllers and Views
- We
start with home Controller, as it is the default controller set in global.asax
to be called first.
When the Index action of the
controller is called we redirect it to our Student Controller, which straight
away returns view to show lists of students if they exist, since it is the first time we
are creating the controller, it shows an empty list, the controller method of Student
fetches the student list from the database, but first it creates the database, thus
acheiving our objective.
- We
create Student Controller, We define actions in the controller for each
operation we want to perform as follows,
using System;
using System.Linq;
using System.Web.Mvc;
using CodeFirstEntities;
using CodeFirstServices.Interfaces;
namespace CodeFirstPortal.Controllers
{
public class StudentController : Controller
{
private readonly IStudentService _studentService;
public StudentController(IStudentService studentService)
{
this._studentService = studentService;
}
[HttpGet]
public ActionResult Details(int? id)
{
var studentDetails = _studentService.GetStudentById((int) id);
if (studentDetails == null) throw new ArgumentNullException("Not Found");
return View(studentDetails);
}
[HttpGet]
public ActionResult Delete(int? id)
{
var studentDetails = _studentService.GetStudentById((int) id);
if (studentDetails == null) throw new ArgumentNullException("Not Found");
return View(studentDetails);
}
[HttpPost]
public ActionResult Delete(Student student)
{
_studentService.DeleteStudent(student.StudentId);
return RedirectToAction("List", "Student");
}
[HttpGet]
public ActionResult Edit(int? id)
{
var studentDetails = _studentService.GetStudentById((int) id);
if (studentDetails == null) throw new ArgumentNullException("Not Found");
return View(studentDetails);
}
[HttpPost]
public ActionResult Edit(Student student)
{
_studentService.UpdateStudent(student);
return RedirectToAction("List", "Student");
}
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Student student)
{
var studentModel = new Student()
{
Address = student.Address,
Country = student.Country,
Name = student.Name,
Age = student.Age,
Email = student.Email
};
_studentService.CreateStudent(studentModel);
return RedirectToAction("List", "Student");
}
[HttpGet]
public ActionResult List()
{
var students = _studentService.GetStudents();
if (students.Any())
{
return View("List", students);
}
return View("List");
}
}
}
There are get and corresponding
Posts for each method responsible for Data Updations. The Constructor of the controller
initializes the Service,we can see it do not create direct instance.
- We create views for every action. It's easy if we right click the controller action
and create view, it automatically creates a view with a Default folder named in
the name of Constructor, so we can create all the views for our operations, and
our solution looks like this:
- Now we are ready
with our application to be executed. Keep your fingers crossed and see the
magic, I have used
_layout
as the master page to give a meaningful look and feel
to my application. You can customize it as well. When you run the application by
pressing F5, we get redirected to the Index view of Student Controller, which
shows list of students, since we are running it first time, and we don't have existing
list, our application shows:
- No
wonder, just have a look at your DataBase. In my case I am using SQL Server 2008.
I got a Database created
automatically with the name CodeFirstApp having Student Table. Now you can
cross verify the table with your entity. It is the same. So we have hit the target
and our database is successfully created.
- Further
Operations
You can
now test the application and perform further CRUD operations in the application
and see the DataBase getting updated (e.g. Create Student).
After Submit by pressing Create, we
get:
Therefore one student created.
We can edit the same student by
pressing edit link, we get the view:
Likewise we can see the details of
already created student:
And delete the student will redirect
to:
I created three students in the same
manner. You can create more and play with the application.
Risk Factor: There is also a Risk
Factor in implementing EntityFramework. If we do any change in the entity, like
deleting, changing property, the context will drop and recreate the database,
which may lead to a loss of your existing data. To avoid this critical
situation, we code some more. We call the SetInitializer
method of DataBase
class
and set it to null in our dataBase Factory Class.
using System.Data.Entity;
namespace CodeFirstData.DBInteractions
{
public class DBFactory : Disposable, IDBFactory
{
public DBFactory()
{
Database.SetInitializer<CodeFirstContext>(null);
}
private CodeFirstContext dataContext;
public CodeFirstContext Get()
{
return dataContext ?? (dataContext = new CodeFirstContext());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
}
Database class is from namespace
System.Data.Entity
, which provides such feature.
Conclusion
In this article we discussed
about creating an application using EntityFramework 4.1 Code First Approach. We
used Inversion of control and Dependency Injection to Resolve Dependency
between layers. We used MVC 3 razor view engine as our UI and integrated the
layers to acheive our objective. The application was a description of simple
CRUD operations on Database. We learned how to use Repository Pattern, Unit of
Work pattern and Unity Framework. You can download the codebase and further
enhance/extend it according to your needs. Happy Coding.