分享

TinyFrame升级之七:重构Repository和Unit Of Work

 ThinkTank_引擎 2015-03-13

首先,重构的想法来源于以下文章:Correct use of Repository and Unit Of Work patterns in ASP.NET MVC,因为我发现在我的框架中,对UnitOfWork使用了错误的设计方法,同时感谢一下文章:Generically Implementing the Unit of Work & Repository Pattern with Entity Framework in MVC & Simplifying Entity Graphs,我的重构设计参考了它。


下面来说说我的具体重构方式。


在原来的代码中,我的Repository<T>泛型继承自IRepository<T>并且在增删改查代码中做了如下处理:



   1:    public virtual void Insert(T entity)

   2:          {

   3:              try

   4:              {

   5:                  if (entity == null)

   6:                      throw new ArgumentException("实体类为空");

   7:                  DbSet.Add(entity);

   8:                  context.SaveChanges();

   9:              }

  10:              catch (DbEntityValidationException dbex)

  11:              {

  12:                  var msg = string.Empty;

  13:                  foreach(var validationErrors in dbex.EntityValidationErrors)

  14:                      foreach(var validateionError in validationErrors.ValidationErrors)

  15:                          msg+=string.Format("Property:{0} Error:{1}",validateionError.PropertyName,validateionError.ErrorMessage);

  16:   

  17:                  var fail = new Exception(msg,dbex);

  18:                  throw fail;

  19:              }

  20:          }



最关键的地方是,我添加了“Context.SaveChanges”方法,这就直接导致UnitOfWork的规则失效。UnitOfWork出现的本身是为了提供事务提交支持。这样直接在Repository中提交,直接导致UnitOfWork功能废弃。


还有个地方就是在前台,通过Autofac注册完毕后,我是这么用的:



   1:   public BookService(IUnitOfWork unitOfWork

   2:              , IBook bookRepository

   3:              , IBookType bookTypeRepository

   4:              , IBookPlace bookPlaceRepository

   5:              , ICacheManager cacheManager

   6:              , ILoggerService logger

   7:              )

   8:          {

   9:              this.unitOfWork = unitOfWork;

  10:              this.bookRepository = bookRepository;

  11:              this.bookTypeRepository = bookTypeRepository;

  12:              this.bookPlaceRepository = bookPlaceRepository;

  13:              this.cacheManager = cacheManager;

  14:              this.logger = logger;

  15:          }

  16:   

  17:          private readonly IUnitOfWork unitOfWork;

  18:          private readonly IBook bookRepository;

  19:          private readonly IBookType bookTypeRepository;

  20:          private readonly IBookPlace bookPlaceRepository;

  21:          private readonly ICacheManager cacheManager;

  22:          private readonly ILoggerService logger;



这样做的话,当以后我们有表删除或者新增的时候,我们不得不维护这样的列表。这完全不符合OO设计原则。


但是如果引入UnitOfWork的话,内部利用Hashtable等实现对Respository的指向,那么在界面我们只要这样写就可以了:



   1:   public BookService(

   2:                IUnitOfWork unitOfWork

   3:              , ICacheManager cacheManager

   4:              , ILoggerService logger

   5:              )

   6:          {

   7:              this.unitOfWork = unitOfWork;

   8:              this.cacheManager = cacheManager;

   9:              this.logger = logger;

  10:          }

  11:   

  12:          private readonly IUnitOfWork unitOfWork;

  13:          private readonly ICacheManager cacheManager;

  14:          private readonly ILoggerService logger;



使用的时候,直接这样实例化就行了:



   1:  var bookPlaceRepository = unitOfWork.Repository<BookPlace>();



这样做完全不用顾虑有新表的添加删除了。代码根本就不用动。


所以,综上两点,UnitOfWork的引入为了解决以下问题:


1.提供全局事务支持。


2.提供对Repository模型的指向。以便于松耦合绑定。


下面是代码重构部分:


IUnitOfWork接口部分:



   1:  using System;

   2:  using TinyFrame.Data.DataRepository;

   3:  using TinyFrame.Data.DomainModel;

   4:   

   5:  namespace TinyFrame.Unitofwork

   6:  {

   7:      public interface IUnitOfWork

   8:      {

   9:          void Commit();

  10:          IRepository<T> Repository<T>() where T : class;

  11:   

  12:          void Dispose(bool disposing);

  13:          void Dispose();

  14:      }

  15:  }



实现部分比较简单,利用Hashtable来保存对Repository的指向:



   1:  using System;

   2:  using System.Data.Entity;

   3:  using TinyFrame.Data.DataRepository;

   4:  using TinyFrame.Data.DomainModel;

   5:  using TinyFrame.Data.DataContext;

   6:  using System.Collections;

   7:   

   8:  namespace TinyFrame.Unitofwork

   9:  {

  10:      public class UnitOfWork : IUnitOfWork

  11:      {

  12:          public UnitOfWork(IDbContext dbContext)

  13:          {

  14:              this.dbContext = dbContext;

  15:          }

  16:   

  17:          private readonly IDbContext dbContext;

  18:          private bool disposed;

  19:          private Hashtable repositorys;

  20:   

  21:          public void Commit()

  22:          {

  23:              dbContext.SaveChanges();

  24:          }

  25:   

  26:          public IRepository<T> Repository<T>() where T:class

  27:          {

  28:              if (repositorys == null)

  29:                  repositorys = new Hashtable();

  30:   

  31:              var type = typeof(T).Name;

  32:   

  33:              if (!repositorys.ContainsKey(type))

  34:              {

  35:                  var repositoryType = typeof(Repository<>);

  36:                  var repositoryInstance = Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)), dbContext);

  37:                  repositorys.Add(type, repositoryInstance);

  38:              }

  39:              return (IRepository<T>)repositorys[type];

  40:          }

  41:   

  42:          #region Dispose method

  43:          public virtual void Dispose(bool disposing)

  44:          {

  45:              if (!disposed)

  46:                  if (disposing) 

  47:                      dbContext.Dispose();

  48:              disposed = true;

  49:          }

  50:          

  51:          public void Dispose()

  52:          {

  53:              Dispose(true);

  54:              GC.SuppressFinalize(this);

  55:          }

  56:          #endregion

  57:      }

  58:  }



第17行,保持对DbContext的引用,以便于进行提交操作。


第26行,Repository<T>泛型方法,以便于动态返回仓储模型。


 


需要注意的是,在Repository<T>的实现中,不要再增删改查里面再添加 DbContext.SaveChanges方法,首先是没意义,其次是完全不符合Repository和UnitOfWork的做法。


最后附图一张,表明我对Repository和UnitOfWork的理解:


QQ截图20140417170836


 


本章源码下载:


点击这里下载


备份下载地址

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多