0% found this document useful (0 votes)
339 views9 pages

Entity Framework and A Generic Repository

This document discusses using the Entity Framework and the Repository Pattern in a .NET application. It proposes creating a generic repository interface and abstract class that implements common data access methods. This allows different backend implementations, like an in-memory collection or Entity Framework data context. It recommends using dependency injection and inversion of control to decouple layers and share a single data context across repositories. The document provides examples of defining interfaces, generic classes, and using a factory and dependency injection container to implement this multi-layered architecture.

Uploaded by

ZoranMatuško
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
339 views9 pages

Entity Framework and A Generic Repository

This document discusses using the Entity Framework and the Repository Pattern in a .NET application. It proposes creating a generic repository interface and abstract class that implements common data access methods. This allows different backend implementations, like an in-memory collection or Entity Framework data context. It recommends using dependency injection and inversion of control to decouple layers and share a single data context across repositories. The document provides examples of defining interfaces, generic classes, and using a factory and dependency injection container to implement this multi-layered architecture.

Uploaded by

ZoranMatuško
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

Entity Framework and a Generic Reposi

Introduction
This article presents a high-level overview of multi-layered
.Net application that implements the Repository Pattern
along with the Entity Framework on its Data Access layer.
The application uses Inversion of Control to decouple
abstractions
(interfaces)
from
implementations.
More specifically,
it
uses
Ninject
to
implement
Dependency Injection.
This separation of concerns allows us to dissect modules
and swap them with other implementations. This is
achieved
by
relying
on
contracts
rather
than
implementations which results on code that is agnostic of
how operations are implemented behind the interfaces.
For example, if you design your business logic to rely on
an interface that follows the Repository Pattern as a
data persistence mechanism, for all intends and purposes,
your business logic will treat this dependency as a
memory domain object collection. Therefore, for
production you could provide an implementation of that
dependency that uses the Entity Framework behind the
scenes to store and retrieve data from a SQL database. For
automated unit testing, you could provide a completely
different implementation that stores and retrieves data
from in-memory objects.
Evidently, you could execute all your tests against the
database; however, this setting greatly helps isolating unit
tests and cut dependencies on other resources, such as
the database, which may need more work to setup up and
tear up for unit testing (especially true if you have other
team members).
Before moving forward, make sure you read What's
Inversion of Control? if you are not familiar with Inversion
of Control or Dependency Injection or would like to hear
more about the advantages of interface-base design
Note: This article does not get into details on how to use
all these technologies and patterns, instead it provides

references to other sources and shows you how they all fit
together in a single application.

The Repository Pattern


The Repository Pattern "mediates between the domain
and data mapping layers using a collection-like interface
for accessing domain objects".
In a multi-layered application the Repository Pattern is
implemented in the Data Access layer
(or Persistence Layer) and it interacts with the Service
Layer and the Data Source by mapping data to objects
back and forth. The following picture shows a web
application that uses a SQL database in the back end.

For each repository in the application we will create both


the interface and the implementation. The interface will
have methods such as: Add, Delete, Find, GetAll, etc. Most
methods will return objects or collections, others such as
Count will return integers. For example, the GetAll method
for the User's Repository will return the list of all User's
objects found in the database.

The operations mentioned above are common enough that


we expect them to see them in all repository classes. For
that reason, we will leverage the power of the Entity
Framework and Link to create a generic interface and a
generic class that implements this "boilerplate" code.

The Generic Interface


?

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public interface IGenericRepository<t> : IDisposable where T : c


{
IQueryable<t> GetAll();
IQueryable<t> FindAllBy(Expression<Func<T, bool>> predicat
T FindFirstBy(Expression<Func<T, bool>> predicate);
T Find(int id);
void Add(T entity);
void Delete(T entity);
void Delete(IQueryable<t> entities);
void Edit(T entity);
int Save();
int Count();
void Refresh(T entity);
}

The Generic Implementation


For the generic class we will use an abstract class that
implements the generic interface in order to provide
common code. Note that this class has a constructor that
takes an IDbContextFactory. This factory allows us to
retrieve the DbContext object that is shared across
other repositories. As a side effect, the creation and
access to this object is centralized into a single location
which facilitates its life cycle management. The
following sections will provide more information on this.
?

1
2
3
4
5
6
7

public abstract class GenericRepository<t> :


IGenericRepository<t>
where T : class
{
protected static ILog log;
public DbContext Context

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
42
43
44
45
46
47
48
49

{ get; set; }

public GenericRepository(IDbContextFactory dbContextFactory)


{
Context = dbContextFactory.GetDbContext();
log = LogManager.GetLogger(GetType());
}
public virtual IQueryable<t> GetAll()
{
return Context.Set<t>();
}

public virtual IQueryable<t> FindAllBy(System.Linq.Expression


{
return Context.Set<t>().Where(predicate);
}

public virtual T FindFirstBy(System.Linq.Expressions.Expressio


{
return Context.Set<t>().FirstOrDefault(predicate);
}
public virtual void Add(T entity)
{
Context.Set<t>().Add(entity);
}
public virtual void Delete(T entity)
{
Context.Set<t>().Remove(entity);
}
public virtual void Delete(IQueryable<t> entities)
{
foreach(T entity in entities.ToList())
Context.Set<t>().Remove(entity);
}

public virtual void Edit(T entity)


{
Context.Entry(entity).State = System.Data.EntityState.Modified
}

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

public virtual int Save()


{
try
{
return Context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationEr
{
log.Error(string.Format("Property: {0} Error: {1}", validati
}
}
}
catch (Exception ex)
{
log.Error("Save failed", ex);
}
return 0;
}
public virtual T Find(int id)
{
return Context.Set<t>().Find(id);
}
public void Refresh(T entity)
{
Context.Entry(entity).Reload();
}
public virtual int Count()
{
return Context.Set<t>().Count();
}
public void Dispose()
{
if (Context != null)

92
93
94

Context.Dispose();
}
}

Usage
This is how you would declare your interface. Notice that
besides declaring the common code (Add, Delete, GetAll,
etc.) it also declares and additional method specific to this
repository GetSubordinates()
?

1
2
3
4

public interface IEmployeeRepository :IGenericRepository<employ


{
IEnumerable<employee> GetSubordinates(int id);
}

Here is the implementation, notice the constructor is


needed
here
in
order
to
obtain
an IDbContextFactory instance
through
Dependency
Injection. Evidently, the class must also implement
GetSubordinates(), this was just a simple example on how
you can leverage the generic repository class and you are
still able to introduce class-specific code.
?

1
2
3
4
5
6
7
8
9
10
11

public class EmployeeRepository : GenericRepository<employee


{
public EmployeeRepository(IDbContextFactory dbContextFactory
: base(dbContextFactory)
{}
public IEnumerable<employee> GetSubordinates(int id)
{
return (Context as DataModelContainer).GetSubordinates(id);
}
}

Sharing the DbContext object by using a


DbContectFactory
The IDbContextFactory interface is very straightforward, it
only declares a method and implements the IDisposable
interface.
?

1
2
3
4

public interface IDbContextFactory : IDisposable


{
DbContext GetDbContext();
}

The implementation is also straightforward. The


DBContextFactory creates an instance of DbContext in its
constructor. For this reason, we can use the factory class
to obtain an instance of DbContext and as long as we use
the same factory we will be sharing the
same DbContext instance across all repositories. This is
actually very easy to do with a dependency injection
container such as Ninject (briefly described in the next
section).
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

public class DbContextFactory : IDbContextFactory


{
private readonly DbContext _context;
public DbContextFactory()
{
_context = new DataModelContainer();
}
public DbContext GetDbContext()
{
return _context;
}
public void Dispose()
{
if (_context != null)
{
_context.Dispose();
GC.SuppressFinalize(this);
}
}
}

Using Ninject as The IoC Container


Ninject is very simple to setup. In a few words you need to
add a few dependencies to your project and a couple of

configuration files. The interesting piece is where you tell


the container the injection pattern it will use (e.g., inject
dependencies through setters or constructors) and also
how to map between interfaces and implementations. For
example, the NinjectWebCommon class provides the
following method to do this mapping:
?

1
2
3
4
5
6
7
8
9
10
11
12
13

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
//repoositories
kernel.Bind<idbcontextfactory>().To<dbcontextfactory>().InRequ
kernel.Bind<iemployeerepository>().To<employeerepository>();
//... more repositories...
}

One thing to note is the use of the Request scope for the
DbContextFactory class which tells Ninject to create a
single instance of this object per HTTP request. In other
words, every time a user requests a page, no mater how
many repository classes are involved, Ninject will create a
single factory class and, therefore, a
single DbContext instance. This also ensures that the
object is destroyed once the request completes. Good
stuff..
Note: In the examples provided here I've been using
dependency injection through constructors.

Putting
it
all
Repositories

together

Using

the

Now that you have created repositories you could either


use them directly on your controllers or on a service class.
The following example shows the Employee Service
obtaining the repositories from the Dependency Injection
container.
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public class EmployeeService : IEmployeeService


{
private readonly IEmployeeRepository _employeeRepository;
private readonly ICompanyService _companyService;

public EmployeeService(IEmployeeRepository _employeeReposit


{
this._employeeRepository = _employeeRepository;
this._companyService = _companyService;
}

//class details here


//notice you can now do _employeeRepository.GetAll() or _compan
//they came for free :)
}

Note: You may have services that depend on multiple


repositories and this is not a problem at all since you have
the flexibility, thanks to Ninject, of deciding whether you
want to use the same instance (Singleton) or create a new
object each time one is requested (Non-Singleton)

Future Work - Unit of Work


Service classes in business logic layer tend to use multiple
repositories simultaneously and sometimes need to have
transactions that either commit all or roll back all actions.
The generic repository class presented here may be not be
transparent enough to control these transactions
efficiently. Therefore, a nice and easy-to-implement
improvement to this class is to use the Unit of
Work concept, which pretty much wraps the repositories
operations to resolve exactly this problem. More info on
this can be found here:
Using Repository and Unit of Work patterns with Entity
Framework 4.0

You might also like