TinyFrame升级之七:重构Repository和Unit Of Work
2014-04-17 17:09
393 查看
首先,重构的想法来源于以下文章:CorrectuseofRepositoryandUnitOfWorkpatternsinASP.NETMVC,因为我发现在我的框架中,对UnitOfWork使用了错误的设计方法,同时感谢一下文章:GenericallyImplementingtheUnitofWork&RepositoryPatternwithEntityFrameworkinMVC&SimplifyingEntityGraphs,我的重构设计参考了它。
下面来说说我的具体重构方式。
在原来的代码中,我的Repository<T>泛型继承自IRepository<T>并且在增删改查代码中做了如下处理:
[code]{
[/code]
最关键的地方是,我添加了“Context.SaveChanges”方法,这就直接导致UnitOfWork的规则失效。UnitOfWork出现的本身是为了提供事务提交支持。这样直接在Repository中提交,直接导致UnitOfWork功能废弃。
还有个地方就是在前台,通过Autofac注册完毕后,我是这么用的:
[code],IBookbookRepository
[/code]
这样做的话,当以后我们有表删除或者新增的时候,我们不得不维护这样的列表。这完全不符合OO设计原则。
但是如果引入UnitOfWork的话,内部利用Hashtable等实现对Respository的指向,那么在界面我们只要这样写就可以了:
[code]IUnitOfWorkunitOfWork
[/code]
使用的时候,直接这样实例化就行了:
这样做完全不用顾虑有新表的添加删除了。代码根本就不用动。
所以,综上两点,UnitOfWork的引入为了解决以下问题:
1.提供全局事务支持。
2.提供对Repository模型的指向。以便于松耦合绑定。
下面是代码重构部分:
IUnitOfWork接口部分:
[code]usingTinyFrame.Data.DataRepository;
[/code]
实现部分比较简单,利用Hashtable来保存对Repository的指向:
[code]usingSystem.Data.Entity;
[/code]
第17行,保持对DbContext的引用,以便于进行提交操作。
第26行,Repository<T>泛型方法,以便于动态返回仓储模型。
需要注意的是,在Repository<T>的实现中,不要再增删改查里面再添加DbContext.SaveChanges方法,首先是没意义,其次是完全不符合Repository和UnitOfWork的做法。
最后附图一张,表明我对Repository和UnitOfWork的理解:
本章源码下载:
点击这里下载
备份下载地址
下面来说说我的具体重构方式。
在原来的代码中,我的Repository<T>泛型继承自IRepository<T>并且在增删改查代码中做了如下处理:
publicvirtualvoidInsert(Tentity)
[code]{
try
{
if(entity==null)
thrownewArgumentException("实体类为空");
DbSet.Add(entity);
context.SaveChanges();
}
catch(DbEntityValidationExceptiondbex)
{
varmsg=string.Empty;
foreach(varvalidationErrorsindbex.EntityValidationErrors)
foreach(varvalidateionErrorinvalidationErrors.ValidationErrors)
msg+=string.Format("Property:{0}Error:{1}",validateionError.PropertyName,validateionError.ErrorMessage);
varfail=newException(msg,dbex);
throwfail;
}
}
[/code]
最关键的地方是,我添加了“Context.SaveChanges”方法,这就直接导致UnitOfWork的规则失效。UnitOfWork出现的本身是为了提供事务提交支持。这样直接在Repository中提交,直接导致UnitOfWork功能废弃。
还有个地方就是在前台,通过Autofac注册完毕后,我是这么用的:
publicBookService(IUnitOfWorkunitOfWork
[code],IBookbookRepository
,IBookTypebookTypeRepository
,IBookPlacebookPlaceRepository
,ICacheManagercacheManager
,ILoggerServicelogger
)
{
this.unitOfWork=unitOfWork;
this.bookRepository=bookRepository;
this.bookTypeRepository=bookTypeRepository;
this.bookPlaceRepository=bookPlaceRepository;
this.cacheManager=cacheManager;
this.logger=logger;
}
privatereadonlyIUnitOfWorkunitOfWork;
privatereadonlyIBookbookRepository;
privatereadonlyIBookTypebookTypeRepository;
privatereadonlyIBookPlacebookPlaceRepository;
privatereadonlyICacheManagercacheManager;
privatereadonlyILoggerServicelogger;
[/code]
这样做的话,当以后我们有表删除或者新增的时候,我们不得不维护这样的列表。这完全不符合OO设计原则。
但是如果引入UnitOfWork的话,内部利用Hashtable等实现对Respository的指向,那么在界面我们只要这样写就可以了:
publicBookService(
[code]IUnitOfWorkunitOfWork
,ICacheManagercacheManager
,ILoggerServicelogger
)
{
this.unitOfWork=unitOfWork;
this.cacheManager=cacheManager;
this.logger=logger;
}
privatereadonlyIUnitOfWorkunitOfWork;
privatereadonlyICacheManagercacheManager;
privatereadonlyILoggerServicelogger;
[/code]
使用的时候,直接这样实例化就行了:
varbookPlaceRepository=unitOfWork.Repository<BookPlace>();
这样做完全不用顾虑有新表的添加删除了。代码根本就不用动。
所以,综上两点,UnitOfWork的引入为了解决以下问题:
1.提供全局事务支持。
2.提供对Repository模型的指向。以便于松耦合绑定。
下面是代码重构部分:
IUnitOfWork接口部分:
usingSystem;
[code]usingTinyFrame.Data.DataRepository;
usingTinyFrame.Data.DomainModel;
namespaceTinyFrame.Unitofwork
{
publicinterfaceIUnitOfWork
{
voidCommit();
IRepository<T>Repository<T>()whereT:class;
voidDispose(booldisposing);
voidDispose();
}
}
[/code]
实现部分比较简单,利用Hashtable来保存对Repository的指向:
usingSystem;
[code]usingSystem.Data.Entity;
usingTinyFrame.Data.DataRepository;
usingTinyFrame.Data.DomainModel;
usingTinyFrame.Data.DataContext;
usingSystem.Collections;
namespaceTinyFrame.Unitofwork
{
publicclassUnitOfWork:IUnitOfWork
{
publicUnitOfWork(IDbContextdbContext)
{
this.dbContext=dbContext;
}
privatereadonlyIDbContextdbContext;
privatebooldisposed;
privateHashtablerepositorys;
publicvoidCommit()
{
dbContext.SaveChanges();
}
publicIRepository<T>Repository<T>()whereT:class
{
if(repositorys==null)
repositorys=newHashtable();
vartype=typeof(T).Name;
if(!repositorys.ContainsKey(type))
{
varrepositoryType=typeof(Repository<>);
varrepositoryInstance=Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)),dbContext);
repositorys.Add(type,repositoryInstance);
}
return(IRepository<T>)repositorys[type];
}
#regionDisposemethod
publicvirtualvoidDispose(booldisposing)
{
if(!disposed)
if(disposing)
dbContext.Dispose();
disposed=true;
}
publicvoidDispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}
[/code]
第17行,保持对DbContext的引用,以便于进行提交操作。
第26行,Repository<T>泛型方法,以便于动态返回仓储模型。
需要注意的是,在Repository<T>的实现中,不要再增删改查里面再添加DbContext.SaveChanges方法,首先是没意义,其次是完全不符合Repository和UnitOfWork的做法。
最后附图一张,表明我对Repository和UnitOfWork的理解:
本章源码下载:
相关文章推荐
- MVC3+EF4.1学习系列(八)-----利用Repository and Unit of Work重构项目
- MVC3+EF4.1学习系列(八)-----利用Repository and Unit of Work重构项目
- .NET MVC4 实训记录之四(Unit of work + Repository)
- MVC+UnitOfWork+Repository+EF
- Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10)
- Using Repository and Unit of Work patterns with Entity Framework 4.0
- 基于NHibernate的UnitOfWork+Repository模式(AutoFac)–Part1
- 基于NHibernate的UnitOfWork+Repository模式(AutoFac)–Part2
- Using Repository and Unit of Work patterns with Entity Framework 4.0
- EntityFramework用法探索(四)Repository和UnitOfWork
- MVC+UnitOfWork+Repository+EF 之我见
- 【无私分享:ASP.NET CORE 项目实战(第五章)】Repository仓储 UnitofWork
- 关于EF Unit of Work Repository的简单用法
- MVC+UnitOfWork+Repository+EF 之我见
- Repository仓储 UnitofWork
- Generic repository pattern and Unit of work with Entity framework
- 【无私分享:ASP.NET CORE 项目实战(第五章)】Repository仓储 UnitofWork
- Unit of work + Repository
- ASP.NET MVC3.0+ JqGrid+Unit Of Work+ Repository/ EF 4.1 CRUD应用 (多层结构)
- 基于NHibernate的UnitOfWork+Repository模式(AutoFac)