您的位置:首页 > 其它

MVC3+EF4.1学习系列(八)-----利用Repository and Unit of Work重构项目

2011-08-05 08:48 597 查看
文章索引和简介

项目最基础的东西已经结束了,但是现在我们的项目还不健全 不利于测试 重复性代码多 层与层之间耦合性高 不利于扩展等问题.今天的这章 主要就是解决这些问题的。再解决这些问题时,自己也产生了很多疑问,理解的也并不是很透彻 ,希望我的疑问能在这里得到解答~~

一.模式介绍

1.Repository

在《企业架构模式》中,通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调。还有请大家参考这个 P OF EAA详细介绍

然后说下我对这个的感觉和疑问 怎么都觉得这个Repository就是以前的dao(dal)层~~ 不过就是通过接口 泛型 与ORM结合 实现了更好的复用 不知道对不~~

2.Unit of Work

先上介绍 Unit Of Work 定义和解释 。主要是解决当有多个操作时,数据的变更 存储 以及事务的处理等 。unit of work是一个记录所有对象模型修改过的信息,在提交的时候,一次性修改,并把结果同步到数据库。 其实我们可以发现 DbContext 已经具备了这样的功能~~ 很大程度实现了Unit of work~ 因为我们savechange()

时 才提交数据的

3.整体概述

运用Repository 和Unit of Work 在 数据层 和业务逻辑层之间 再创建一个抽象层 。它将帮我们隔离变化,并且更利于测试.

下面借用下原文的图 说明下使用Repository 和Unit of Work和不使用的区别

原文控制器代码

namespace ContosoUniversity.Controllers
{
public class CourseController : Controller
{
private UnitOfWork unitOfWork = new UnitOfWork();

//
// GET: /Course/

public ViewResult Index()
{
var courses = unitOfWork.CourseRepository.Get(includeProperties: "Department");
return View(courses.ToList());
}

//
// GET: /Course/Details/5

public ViewResult Details(int id)
{
Course course = unitOfWork.CourseRepository.GetByID(id);
return View(course);
}

//
// GET: /Course/Create

public ActionResult Create()
{
PopulateDepartmentsDropDownList();
return View();
}

[HttpPost]
public ActionResult Create(Course course)
{
try
{
if (ModelState.IsValid)
{
unitOfWork.CourseRepository.Insert(course);
unitOfWork.Save();
return RedirectToAction("Index");
}
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}

public ActionResult Edit(int id)
{
Course course = unitOfWork.CourseRepository.GetByID(id);
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}

[HttpPost]
public ActionResult Edit(Course course)
{
try
{
if (ModelState.IsValid)
{
unitOfWork.CourseRepository.Update(course);
unitOfWork.Save();
return RedirectToAction("Index");
}
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
PopulateDepartmentsDropDownList(course.DepartmentID);
return View(course);
}

private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
{
var departmentsQuery = unitOfWork.DepartmentRepository.Get(
orderBy: q => q.OrderBy(d => d.Name));
ViewBag.DepartmentID = new SelectList(departmentsQuery, "DepartmentID", "Name", selectedDepartment);
}

//
// GET: /Course/Delete/5

public ActionResult Delete(int id)
{
Course course = unitOfWork.CourseRepository.GetByID(id);
return View(course);
}

//
// POST: /Course/Delete/5

[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Course course = unitOfWork.CourseRepository.GetByID(id);
unitOfWork.CourseRepository.Delete(id);
unitOfWork.Save();
return RedirectToAction("Index");
}

protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
}
}


原文的这个demo 并没有很好的体现出 使用 unit of work 的好处 因为他的这个例子没有出现一个逻辑用到多个资源库的 希望大家明白这点~~ 等以后的文章

我会写个完整的demo 来说明这点 这里大家先看下 明白怎么回事就行~

六.EF+MVC框架的疑问

1.是否有必要实现 IUnitOfWork 接口?代码大概这样

public interface IUnitOfWork

{

void Save();

IStudentRepository StudentRepository { get; }

}


实现接口

public class UnitOfWork : IUnitOfWork

{

private SchoolEntities context = new SchoolEntities();

private IStudentRepository studentRepository;

public IStudentRepository StudentRepository

{

get

{

if (this.studentRepository == null)

{

this.studentRepository = new StudentRepository(context);

}

return studentRepository;

}

}

public void Save()

{

context.SaveChanges();

}

}


控制器

private IUnitOfWork unitOfWork;

public StudentController () : this (new UnitOfWork())

{

}

public StudentController (IUnitOfWork unitOfWork)

{

this.unitOfWork = unitOfWork;

}


2. 是否有必要再 加上一个 服务层 service 这个层 在 控制器和dal 之间 也就是 通过 unitofwork 调用的东西等 都写在servie上 这样控制器里的代码会变得非常少, 个人觉得应该加上service层的,但是是否需要加Iservice 接口 加这个接口 能获得哪些好处 ? 我一直觉得 只用 给数据访问层 实现接口 就行 ~~

3. 这里我们是用的unit of work 完成了事务的一致性 以前我是使用

using (TransactionScope transaction = new TransactionScope()){
....

transaction.Complete();
}


用这个来实现 事务一致性 不知道大家觉得 这个和 unit of work 比怎么样? 我暂时还没研究这个~ 但是 小城岁月 对这个做了很好的介绍 感谢小城~ 大家可以参考他的这篇文章


4. 我们的缓存 比如用的 mongodb 这个写到哪层比较好呢?

六.总结

经过重构 代码终于有些项目的样子了~~ 下节讲讲EF的其他一些功能 如 直接执行SQL语句,关闭跟踪状态这些~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: