仓储和工作单元模式是用来在数据访问层和业务逻辑层之间创建一个抽象层。
图很重要
首先我们先搭建好空的框架,准备基本的结构和一些测试数据。(新建一个项目XEngine)
然后建立model->SysUser, SysRole , SysUserRole
还有安装ef(为什么我的一直安装不上,狗屁电脑)
在建立dal
新建类 XEngineContext.cs
新建类 XEngineInitializer.cs具体(http://www.cnblogs.com/miro/p/4806199.html)
.新建文件夹 Repositories(用来储存仓库类)
创建接口 ISysUserRepository
接口中声明了一组典型的CRUD方法。
IEnumerable<SysUser> GetUsers();
SysUser GetUserBy(int userID);
void InsertUser(SysUser user);
void DeleteUser(int userID);
void UpdateUser(SysUser user);
void Save();
创建对应的仓储类 SysUserRepository
创建类 SysUserRepository, 实现接口 ISysUserRepository
ef中的EntityState
添加、修改、删除就是Added、Modified、Deleted
当调用SaveChanges方法的时候,EF会根据EntityState这个枚举检测到实体的状态,然后执行相应的增/删/改操作。它们的具体意思分别为:
- Detached:对象存在,但未由对象服务跟踪。在创建实体之后、但将其添加到对象上下文之前,该实体处于此状态;
- Unchanged:自对象加载到上下文中后,或自上次调用 System.Data.Objects.ObjectContext.SaveChanges() 方法后,此对象尚未经过修改;
- Added:对象已添加到对象上下文,但尚未调用 System.Data.Objects.ObjectContext.SaveChanges() 方法;
- Deleted:使用 System.Data.Objects.ObjectContext.DeleteObject(System.Object) 方法从对象上下文中删除了对象;
- Modified:对象已更改,但尚未调用 System.Data.Objects.ObjectContext.SaveChanges() 方法。
Controller中使用SysUser仓储类
我们新建个Controller : UserController
用 List 模板生成视图。
修改Controller如下:
private IGenericRepository<SysUser> userRepository
= new GenericRepository<SysUser>(new XEngineContext());
public ActionResult Index()
{
var users = userRepository.Get();
return View(users);
}
我们增加了一个抽象层,将数据连接的部分移到Repository中去,这样实现了Controller和数据层的解耦。
使用 generic repository去除冗余代码
使用unit of work保证所有repositories使用同一个 context
新建一个unit of work class 用来协调多个repositories工作, 通过创建单一的context让大家共享。
先解决代码冗余的问题
仿照ISysUserRepository和SysUserRepository,新建IGenericRepository和GenericRepository(引用TEntity)
通过泛型类已经消除了冗余。
如果有其他实体只需要改变传入的TEntity就可以了,不需要再重新创建repository class
在DAL文件夹中新建一个类UnitOfWork用来负责context的一致性:
当使用多个repositories时,共享同一个context
我们把使用多个repositories的一系列操作称为一个 unit of work
当一个unit of work完成时,我们调用context的SaveChanges方法来完成实际的更改。
把 GenericRepository.cs 中的Save 和 Dispose 删除, 移到UnitOfWork中。
将IGenericRepository 中的IDisposable接口继承也去掉.
Save & Dispose 的工作统一在UnitOfWork中完成。
修改UserController
private UnitOfWork unitOfWork = new UnitOfWork();
// GET: User
public ActionResult Index()
{
var users = unitOfWork.SysUserRepository.Get(orderBy:q=>q.OrderBy(u=>u.Name));
return View(users);
}