如何在 ASP MVC 中实现工作单元、存储库和业务逻辑?
Posted
技术标签:
【中文标题】如何在 ASP MVC 中实现工作单元、存储库和业务逻辑?【英文标题】:How do implement Unit of Work, Repository and Business Logic in ASP MVC? 【发布时间】:2013-09-23 23:59:34 【问题描述】:我目前被分配到一个使用实体框架的 asp mvc 项目。这将是一个业务线应用程序。我想使用存储库和工作单元模式开发这个应用程序。我是这种模式的新手(也是 .net 的新手),我在理解这种模式以及如何实现它时遇到了问题。
我阅读了很多文章,我认为这就是我的应用程序应该是这样的
实体框架 -> 存储库 -> 工作单元 -> 客户端(Asp MVC)
我附上了这篇文章的一些代码 http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
using System;
using ContosoUniversity.Models;
namespace ContosoUniversity.DAL
public class UnitOfWork : IDisposable
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
private GenericRepository<Course> courseRepository;
public GenericRepository<Department> DepartmentRepository
get
if (this.departmentRepository == null)
this.departmentRepository = new GenericRepository<Department>(context);
return departmentRepository;
public GenericRepository<Course> CourseRepository
get
if (this.courseRepository == null)
this.courseRepository = new GenericRepository<Course>(context);
return courseRepository;
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);
GC.SuppressFinalize(this);
工作单元将具有存储库,并将在创建时创建 DBContext
因此控制器将在创建时创建工作单元。 要显示数据,我将使用此代码
var department = UoW.departmentRepository.Find(1);
return View(department);
当客户端点击保存按钮时,我将运行此代码
UoW.departmentRepository.Update(department);
UoW.Save();
我的问题:
如果从数据检索到客户端单击保存按钮需要几个小时,该怎么办。据我所知,我们必须尽可能缩短上下文。
我应该把业务逻辑放在哪里?我把它放在存储库中吗?所以我会在保存之前调用 UoW.departmentRepository.Validate(department) 。但是,如果我需要验证与其他实体相关的实体怎么办。我打电话给 UoW.departmentRepository.Validate(course, department)?
是否有此类应用程序的完整示例项目?
编辑
按照 Ant P 的建议,我需要添加另一层来放置我的业务逻辑。
这就是我到目前为止所做的事情
工作单元:
public class UnitOfWork : IDisposable
private DBContext _context = new DBContext();
public DBContext Context
get
return this._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);
GC.SuppressFinalize(this);
业务逻辑:
public class SalesBusinessLogic : IDisposable
private ICustomerRepository _customerRepo;
private ISalesRepository _salesRepo;
private UnitOfWork _uow;
public SalesBusinessLogic(UnitOfWork uow)
this._uow = uow;
public ICustomerRepository CustomerRepo
get
if (this._customerRepo == null)
this._customerRepo = new CustomerRepository(this._uow);
return this._customerRepo;
public ISalesRepository SalesRepo
get
if (this._salesRepo == null)
this._salesRepo = new SalesRepository(this._uow);
return this._salesRepo;
public bool Validate(Sales sales)
//this is where validation performed
return true;
控制器:
public SalesController : Controller
private UnitOfWork _uow = new UnitOfWork();
private SalesBusinessLogic _bl = new SalesBusinessLogic(this._uow);
public ActionResult Index()
var sales = _bl.SalesRepo.Find(1);
sales.CustomerID = 1;
if _bl.Validate(sales)
_bl.SalesRepo.Update(sales);
_uow.Save();
return View(sales);
这里 UnitOfWork 仅充当 dbcontext 的提供者,它将被业务逻辑和存储库使用。 存储库将在 BusinessLogic 类中。
服务器端验证将由 BusinessLogic 处理,客户端验证将由 Web 层中的视图模型处理。
我唯一担心的是 UnitofWork 中的 dbcontext 是可公开访问的。
我的方向正确吗?
【问题讨论】:
请注意:在您的SalesBusinessLogic
类中,您继承了IDisposable
的形式,但您还没有实现Dispose
方法。对于上面的代码,这将是:public void Dispose() _uow.Dispose();
【参考方案1】:
如果从数据检索到客户端单击保存按钮需要数小时怎么办。据我所知,我们必须尽可能缩短上下文。
这不是问题 - 控制器是根据请求实例化的。当用户查看页面时,它不会持续存在。听起来您误解了控制器在什么时候被实例化。当您在控制器的构造函数中实例化 UnitOfWork 时,流程如下所示:
用户发出 POST 请求(通过单击“保存”)。 请求到达服务器并实例化控制器(从而实例化工作单元)。 动作方法被调用。 工作单元已部署。我应该把业务逻辑放在哪里?我把它放在存储库中吗?所以我会在保存之前调用 UoW.departmentRepository.Validate(department) 。但是,如果我需要验证与其他实体相关的实体怎么办。我打电话给 UoW.departmentRepository.Validate(course, department)?
通常,您的业务逻辑会被抽象为一个单独的层,位于您的 Web 应用程序和存储库之间。向您展示直接注入控制器的存储库的教程假定您具有“精简”业务逻辑。
但是,验证绝对不是存储库的工作。您应该为每个视图创建一个单独的视图模型并在控制器中验证它们。存储库应该仅用于 CRUD 操作。
【讨论】:
好答案+1,如果您需要“验证与其他实体相关的实体”,那么这里有一个示例,说明如何使用实体框架通过工作单元对数据库进行验证: ***.com/a/16647237/150342 @AntP 感谢您解释控制器的生命周期。我是 .net 的新手,还有很多东西需要学习。所以我需要将业务逻辑放在另一个层/dll中。但正如科林所说,如果验证需要访问数据库/dbcontext 怎么办?所以业务逻辑必须参考实体框架。以及业务逻辑是什么样的?它在课堂上是否有 uow 和存储库?控制器应该如何调用业务逻辑?你能详细说明一下吗?也许放一些示例代码或指导我看一两篇文章? @colin 感谢您的链接。但我应该把验证放在哪里?它在 DAL 还是 BLL 中?从链接中,验证在 uow 中执行 天哪 ;-) 这是我没有资格回答的问题。你有客户端验证和服务器端验证,有时你需要去数据库进行验证。如果您只需要检查一个字段是否是唯一的,那么我认为这非常适合数据层。我的链接显示了上下文类中的验证以及我如何将其反馈给 ui(使用 Ant 描述的“瘦”业务逻辑)。如果您有更复杂的业务验证,那么它可能适合 BLL。这值得一读:msdn.microsoft.com/en-us/data/gg193959.aspx @Reynaldi 你走在正确的轨道上——我会考虑在你的控制器之间引入服务/BLL,然后将你的 UnitOfWork 提供给它。但是,如果对 DB 的验证很简单,那么在控制器中进行验证并没有错 - 避免不必要的抽象。以上是关于如何在 ASP MVC 中实现工作单元、存储库和业务逻辑?的主要内容,如果未能解决你的问题,请参考以下文章