下载PDF_Article.zip - 606.8 KB 下载SqlScriptToCreateTable.zip - 537 B 下载SqlScriptToCreateDatabase.zip - 872 B 下载MVCWithEntityFrameworkGenericRepPattern.zip - 2.3 MB 下载LearningMVCRepoPattern.zip - 2.3 MB 介绍 在使用实体框架的MVC3应用程序中创建通用存储库模式是我们学习MVC过程中将要讨论的最后一个主题。 本文将重点讨论工作单元模式和存储库模式,并展示如何在可能创建多个存储库类时在MVC应用程序中执行CRUD操作。为了克服这种可能性和开销,我们为所有其他存储库创建了一个通用的存储库类,并实现了一个工作单元模式来提供抽象。 学习MVC 只是为了提醒我们学习MVC的完整路线图, 第一部分:介绍MVC架构和关注点分离第2部分:从头创建MVC应用程序并使用LINQ to SQL将其与数据库连接第3部分:使用EntityFramework DB-First方法连接MVC应用程序。第4部分:使用EntityFramework代码优先方法连接MVC应用程序第5部分:使用EntityFramework. 在MVC应用程序中实现存储库模式第6部分:使用EntityFramework. 在MVC应用程序中实现通用存储库模式和工作单元模式 Pre-requisites 在我们开始文章之前,有几个先决条件, 在本系列文章的第5部分中,我们创建了运行的示例应用程序。我们有实体框架4.1包或DLL在我们的本地文件系统。我们了解了MVC应用程序是如何创建的(遵循本系列的第二部分)。 为什么通用存储库 在上一篇文章中,我们已经讨论了什么是存储库模式以及为什么需要存储库模式。我们为执行CRUD操作创建了一个用户存储库,但是考虑一下需要10个这样的存储库的场景。 我们要创建这些类吗?不好的是,这会导致大量的冗余代码。因此,为了克服这种情况,我们将创建一个通用的储存库类,该类将由一个属性调用来创建一个新的储存库,这样我们就不会产生很多类,而且还会转义冗余代码。此外,我们节省了大量可能浪费在创建这些类上的时间。 工作单元模式 根据Martin Fowler的工作单元模式,“维护受业务事务影响的对象列表,并协调更改的编写和并发问题的解决。” 在MSDN中,工作单元模式不一定是您自己显式构建的,但是这种模式几乎出现在每个持久性工具中。NHibernate中的ITransaction接口,LINQ to SQL中的DataContext类,以及实体框架中的ObjectContext类都是工作单元的例子。对于这个问题,古老的数据集可以用作一个工作单元。 其他时候,您可能希望编写自己的特定于应用程序的工作单元接口或类,以包装来自持久性工具的内部工作单元。这样做的原因有很多。您可能希望将特定于应用程序的日志记录、跟踪或错误处理添加到事务管理中。也许您希望从应用程序的其余部分封装持久性工具的细节。您可能希望使用这种额外的封装,以便稍后更容易地交换持久性技术。或者您可能希望提高系统的可测试性。许多来自普通持久性工具的内置工作单元实现在自动化单元测试场景中很难处理。 工作类的单元可以具有将实体标记为已修改、新创建或已删除的方法。工作单元还将具有提交或回滚所有更改的方法。 工作单元的重要职责是: 管理事务。对数据库的插入、删除和更新进行排序。防止重复更新。在一个工作单元对象的单一使用中,代码的不同部分可能会将同一个Invoice对象标记为已更改,但是工作类的单元将只向数据库发出一个更新命令。 使用工作单元模式的价值在于将代码的其余部分从这些关注点中解放出来,这样您就可以将精力集中在业务逻辑上。 为什么使用工作单元? Martin Fowler说:“当你从数据库中提取数据时,跟踪你的变化是很重要的;否则,该数据将不会被写回数据库。类似地,您必须插入您创建的新对象,并删除您删除的任何对象。 您可以在每次更改对象模型时更改数据库,但这可能会导致大量非常小的数据库调用,从而导致速度非常慢。此外,它要求您为整个交互打开一个事务,如果您有一个跨越多个请求的业务事务,这是不切实际的。如果你需要跟踪你读过的东西,这样你就可以避开它们,情况就更糟了不一致的读取。 工作单元跟踪并负责您在业务事务期间所做的可能影响数据库的所有工作。当你完成时,它会计算出你的工作需要做的所有事情来改变数据库。” 你看,我不需要过多地集中在理论上,我们已经有了很好的定义,我们所需要的是把它们以正确的格式堆叠起来。 使用工作单元 使用工作单元模式的最佳方法之一是允许不同的类和服务参与单个逻辑事务。这里的关键点是,您希望异类和服务在能够在单个事务中登记的同时保持彼此的忽略。传统上,您可以通过使用事务协调器(如MTS/COM+或较新的系统)来实现这一点。交易名称空间。就个人而言,我更喜欢使用工作单元模式来允许不相关的类和服务参与逻辑事务,因为我认为它使代码更显式、更容易理解和更容易进行单元测试(来自MSDN)。 创建通用存储库 减少冗余…… 步骤1:在Visual Studio中打开在第5部分中创建的现有MVC3应用程序。 右键单击学习MVC项目文件夹,创建一个名为GenericRepository的文件夹,并将一个名为genericrepositore .cs的类添加到该文件夹中。 类genericrepositore .cs的代码如下: 隐藏,收缩,复制Codeusing System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Linq.Expressions; namespace LearningMVC.GenericRepository { public class GenericRepository<TEntity> where TEntity : class { internal MVCEntities context; internal DbSet<TEntity> dbSet; public GenericRepository(MVCEntities context) { this.context = context; this.dbSet = context.Set<TEntity>(); } public virtual IEnumerable<TEntity> Get() { IQueryable<TEntity> query = dbSet; return query.ToList(); } public virtual TEntity GetByID(object id) { return dbSet.Find(id); } public virtual void Insert(TEntity entity) { dbSet.Add(entity); } public virtual void Delete(object id) { TEntity entityToDelete = dbSet.Find(id); Delete(entityToDelete); } public virtual void Delete(TEntity entityToDelete) { if (context.Entry(entityToDelete).State == EntityState.Detached) { dbSet.Attach(entityToDelete); } dbSet.Remove(entityToDelete); } public virtual void Update(TEntity entityToUpdate) { dbSet.Attach(entityToUpdate); context.Entry(entityToUpdate).State = EntityState.Modified; } } } 我们可以看到,我们已经创建了泛型方法,并且类也是泛型的,当实例化这个类时,我们可以传递任何模型,该类将在其上作为存储库并服务于此目的。 TEntity是任何模型/域/实体类。如前所述,MVCEntities是我们的DBContext。 步骤3:实现UnitOfWork:在LearningMVC项目下创建一个名为UnitOfWork的文件夹,并在该文件夹中添加一个类UnitOfWork.cs。 该类代码如下: 隐藏,收缩,复制Codeusing System; using LearningMVC.GenericRepository; namespace LearningMVC.UnitOfWork { public class UnitOfWork : IDisposable { private MVCEntities context = new MVCEntities(); private GenericRepository<User> userRepository; public GenericRepository<User> UserRepository { get { if (this.userRepository == null) this.userRepository = new GenericRepository<User>(context); return userRepository; } } 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); } } } 我们看到这个类为要释放的该类对象实现了IDisposable接口。 我们在这个类中创建了DBContext的对象,注意,之前它是用来从控制器在Repository类中传递的。 现在是创建用户存储库的时候了。我们在代码中看到,一个名为userRepository的变量被声明为私有genericrepository>userRepository;类型为用户实体到TEntity模板服务的GenericRepository。 然后以一种非常简单的方式为同一个userRepository变量创建一个属性, 隐藏,复制Codepublic GenericRepository<User> UserRepository { get { if (this.userRepository == null) this.userRepository = new GenericRepository<User>(context); return userRepository; } } 即。只有6-7行代码。你猜怎么着?创建了我们的用户存储库。 (来自谷歌) 您可以看到,它就是这么简单,您只需创建简单的属性就可以创建任意多的存储库,而不需要创建单独的类。现在你可以自己完成剩下的故事了,困惑吗??对,这是DBOperations。 步骤4:在MyController中,声明一个变量unitOfWork为: 隐藏,复制Codeprivate UnitOfWork.UnitOfWork unitOfWork = new UnitOfWork.UnitOfWork(); 现在unitOfWork类的unitOfWork实例拥有所有的存储库属性,如果我们按下“。之后,它将显示存储库。因此,我们可以选择创建的任何存储库并对其执行CRUD操作。 我们的索引行动: 隐藏,复制Codepublic ActionResult Index() { var userList = from user in unitOfWork.UserRepository.Get() select user; var users = new List<LearningMVC.Models.UserList>(); if (userList.Any()) { foreach (var user in userList) { users.Add(new LearningMVC.Models.UserList() { UserId = user.UserId, Address = user.Address, Company = user.Company, FirstName = user.FirstName, LastName = user.LastName, Designation = user.Designation, EMail = user.EMail, PhoneNo = user.PhoneNo }); } } ViewBag.FirstName = "My First Name"; ViewData["FirstName"] = "My First Name"; if(TempData.Any()) { var tempData = TempData["TempData Name"]; } return View(users); } 在这里, unitOfWork。UserRepository——比;访问UserRepository。unitOfWork.UserRepository.Get()→访问通用的Get()方法以获取所有用户。 之前我们用MyController构造函数,像: 隐藏,复制Codepublic MyController() { this.userRepository = new UserRepository(new MVCEntities()); } 现在,不需要编写那个构造函数,实际上您可以删除我们在学习MVC的第5部分中创建的UserRepository类和接口。 我希望您也可以为其他CRUD操作编写操作。 细节 隐藏,复制Codepublic ActionResult Details(int id) { var userDetails = unitOfWork.UserRepository.GetByID(id); var user = new LearningMVC.Models.UserList(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user); } 创建: 隐藏,复制Code[HttpPost] public ActionResult Create(LearningMVC.Models.UserList userDetails) { try { var user = new User(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } unitOfWork.UserRepository.Insert(user); unitOfWork.Save(); return RedirectToAction("Index"); } catch { return View(); } } 编辑: 隐藏,收缩,复制Codepublic ActionResult Edit(int id) { var userDetails = unitOfWork.UserRepository.GetByID(id); var user = new LearningMVC.Models.UserList(); if (userDetails != null) { user.UserId = userDetails.UserId; user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user); } [HttpPost] public ActionResult Edit(int id, User userDetails) { TempData["TempData Name"] = "Akhil"; try { var user = unitOfWork.UserRepository.GetByID(id); user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; unitOfWork.UserRepository.Update(user); unitOfWork.Save(); return RedirectToAction("Index"); } 删除: 隐藏,收缩,复制Codepublic ActionResult Delete(int id) { var user = new LearningMVC.Models.UserList(); var userDetails = unitOfWork.UserRepository.GetByID(id); if (userDetails != null) { user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName; user.Address = userDetails.Address; user.PhoneNo = userDetails.PhoneNo; user.EMail = userDetails.EMail; user.Company = userDetails.Company; user.Designation = userDetails.Designation; } return View(user); } [HttpPost] public ActionResult Delete(int id, LearningMVC.Models.UserList userDetails) { try { var user = unitOfWork.UserRepository.GetByID(id); if (user != null) { unitOfWork.UserRepository.Delete(id); unitOfWork.Save(); } return RedirectToAction("Index"); } catch { return View(); } } 注意:图像取自谷歌图像。 结论 我们现在也知道了如何创建通用存储库,以及如何使用它执行CRUD操作。 我们还详细学习了单元作业模式。现在您有足够的资格和信心在企业应用程序中应用这些概念。这是MVC系列的最后一部分,如果您想讨论任何特定主题,请告诉我,或者我们也可以开始其他系列。 编码:快乐), 本文转载于:http://www.diyabc.com/frontweb/news419.html