原文 Generic repository pattern and Unit of work with Entity framework
Repository pattern is an abstraction layer between your business logic layer and data access layer. This abstract layer contains methods to server data from data layer to business layer. Now, changes in your data layer cannot affect the business layer directly.
For more information about repository pattern or unit of work visit this article. Below is my approach how to implement repository pattern and unit of work with entity framework.
1. Create IGenericRepository interface
1
2
3
4
5
6
7
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
50
51
52
53
54
55
56
57
|
public
interface
IGenericRepository<TEntity>
{
/// <summary>
/// Get all entities from db
/// </summary>
/// <param name="filter"></param>
/// <param name="orderBy"></param>
/// <param name="includes"></param>
/// <returns></returns>
List<TEntity> Get(
Expression<Func<TEntity,
bool
>> filter =
null
,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy =
null
,
params
Expression<Func<TEntity,
object
>>[] includes);
/// <summary>
/// Get query for entity
/// </summary>
/// <param name="filter"></param>
/// <param name="orderBy"></param>
/// <returns></returns>
IQueryable<TEntity> Query(Expression<Func<TEntity,
bool
>> filter =
null
, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy =
null
);
/// <summary>
/// Get single entity by primary key
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
TEntity GetById(
object
id);
/// <summary>
/// Get first or default entity by filter
/// </summary>
/// <param name="filter"></param>
/// <param name="includes"></param>
/// <returns></returns>
TEntity GetFirstOrDefault(
Expression<Func<TEntity,
bool
>> filter =
null
,
params
Expression<Func<TEntity,
object
>>[] includes);
/// <summary>
/// Insert entity to db
/// </summary>
/// <param name="entity"></param>
void
Insert(TEntity entity);
/// <summary>
/// Update entity in db
/// </summary>
/// <param name="entity"></param>
void
Update(TEntity entity);
/// <summary>
/// Delete entity from db by primary key
/// </summary>
/// <param name="id"></param>
void
Delete(
object
id);
}
|
2. Create GenericRepository class to implement interface
1
2
3
4
5
6
7
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
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
|
public
class
GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity :
class
{
private
DbContext context;
private
DbSet<TEntity> dbSet;
public
GenericRepository(DbContext context)
{
this
.context = context;
this
.dbSet = context.Set<TEntity>();
}
public
virtual
List<TEntity> Get(Expression<Func<TEntity,
bool
>> filter =
null
, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy =
null
,
params
Expression<Func<TEntity,
object
>>[] includes)
{
IQueryable<TEntity> query = dbSet;
foreach
(Expression<Func<TEntity,
object
>> include
in
includes)
query = query.Include(include);
if
(filter !=
null
)
query = query.Where(filter);
if
(orderBy !=
null
)
query = orderBy(query);
return
query.ToList();
}
public
virtual
IQueryable<TEntity> Query(Expression<Func<TEntity,
bool
>> filter =
null
, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy =
null
)
{
IQueryable<TEntity> query = dbSet;
if
(filter !=
null
)
query = query.Where(filter);
if
(orderBy !=
null
)
query = orderBy(query);
return
query;
}
public
virtual
TEntity GetById(
object
id)
{
return
dbSet.Find(id);
}
public
virtual
TEntity GetFirstOrDefault(Expression<Func<TEntity,
bool
>> filter =
null
,
params
Expression<Func<TEntity,
object
>>[] includes)
{
IQueryable<TEntity> query = dbSet;
foreach
(Expression<Func<TEntity,
object
>> include
in
includes)
query = query.Include(include);
return
query.FirstOrDefault(filter);
}
public
virtual
void
Insert(TEntity entity)
{
dbSet.Add(entity);
}
public
virtual
void
Update(TEntity entity)
{
dbSet.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
public
virtual
void
Delete(
object
id)
{
TEntity entityToDelete = dbSet.Find(id);
if
(context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
}
|
3. Create IUnitOfWork interface
1
2
3
4
5
|
public
interface
IUnitOfWork
{
IGenericRepository<Model> ModelRepository {
get
; }
void
Save();
}
|
4. Create UnitOfWork class to implement interface
1
2
3
4
5
6
7
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
|
public
class
UnitOfWork : IUnitOfWork, System.IDisposable
{
private
readonly
MyDatabaseContext _context;
private
IGenericRepository<Model> _modelRepository;
public
UnitOfWork(MyDatabaseContext context)
{
_context = context;
}
public
IGenericRepository<Model> ModelRepository
{
get
{
return
_modelRepository ?? (_modelRepository =
new
GenericRepository<Model>(_context)); }
}
public
void
Save()
{
_context.SaveChanges();
}
private
bool
disposed =
false
;
protected
virtual
void
Dispose(
bool
disposing)
{
if
(!
this
.disposed)
{
if
(disposing)
{
_context.Dispose();
}
}
this
.disposed =
true
;
}
public
void
Dispose()
{
Dispose(
true
);
System.GC.SuppressFinalize(
this
);
}
}
|
5. Usage in controller
1
2
3
4
5
6
7
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
|
public
class
HomeController : Controller
{
private
IUnitOfWork _unitOfWork;
public
HomeController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
//
// GET: /Home/
public
ActionResult Index()
{
// get all models (all properties)
List<Model> modelList = _unitOfWork.ModelRepository.Get(m => m.FirstName ==
"Jan"
|| m.LastName ==
"Holinka"
, includeProperties:
"Account"
);
// get all models (some properties)
List<ModelDto> modelDtoList = _unitOfWork.UserRepository
.Query(x => x.FirstName ==
"Jan"
|| x.LastName ==
"Holinka"
)
.Select(x =>
new
ModelDto
{
FirstName = x.FirstName,
LastName = x.LastName
})
.ToList();
return
View(
"Index"
);
}
// show list of models in view
return
View(modelList);
}
}
public
class
ModelDto
{
public
string
FirstName {
get
;
set
; }
public
string
LastName {
get
;
set
; }
}
|