工作单元模式
最近趁过年期间上网了解一些设计模式,无意中看到工作单元模式,眼睛一亮,之前的项目怎么就不懂用到这个模式呢?后悔不已,进园这么久也没留下什么,今天抽空写篇博文好好说说工作单元模式,在项目中的运用,它的好处还有自己的几个疑点。
什么是工作单元模式呢?术语上解释为:维护一个受业务事务影响的对象列表,并协调写入更改内容和并发问题的解决方案。
举个简单例子,有2张表,一张是文章类别表,一张是文章表,文章表中有一个外键对应着文章类别表ID,现在有个业务删除某个类别的同时需要删除该类别下的文章,我们可以把这个业务看成一个工作单元,在该工作单元下分别有2个步骤,第一删除该类别下的所有文章,第二在类别表中删除该类。就在这时意外出现了,在执行第一步操作的时候程序运行正常,非常perfection,但是在执行第二步骤的时候出现荡机,数据库崩溃了或者其他的意外,第二步并没执行!大家会觉得处理这种情况直接加一个事务来处理不就行了,出现意外直接回滚,也确实如此,但是大量的数据增删改操作中,我们没办法对每一个操作进行事务处理,除了给编码增加负担外,有些操作也没必要这么处理,而且在大量的数据操作中,很容易出现并发的问题,而这个工作单元模式就可以很有效的改良此问题。
工作单元需要知道应该跟踪哪个对象,在这里需要先明白2个基本方法,调用者注册(对象的用户必须记得注册到工作单元),对象注册(对象把自身注册到工作单元)
OK! 直接上源码
先写一个工作单元接口 里面有注册添加 更改 删除 和把所有已经注册的数据进行提交 的Commit操作
这里有2个参数 第一个object 即为要跟踪的对象 这里可以是数据实体。
第二个参数工作单元的一个数据操作接口 每个对象所对应的仓储需继承并实现其方法。
代码
namespace UnitOfWork
{
publicinterface IUnitOfWork
{
void RegisterAdded(object entity, IUnitOfWorkRepository repository);
void RegisterChanged(object entity, IUnitOfWorkRepository repository);
void RegisterRemoved(object entity, IUnitOfWorkRepository repository);
void Commit();
}
}
仓储操作接口
代码
namespace UnitOfWork
{
publicinterface IUnitOfWorkRepository
{
void NewItem(object item);
void UpdatedItem(object item);
void DeletedItem(object item);
}
}
之后建UnitOfWork.cs 文件实现该IUnitOfWork类 这里用TransactionScope 来实现事务的处理,用 字典来缓存注册的信息
代码
using System.Collections.Generic;
using System.Transactions;
namespace UnitOfWork
{
publicclass UnitOfWork : IUnitOfWork
{
private Dictionary<object, IUnitOfWorkRepository> addedEntities;
private Dictionary<object, IUnitOfWorkRepository> changedEntities;
private Dictionary<object, IUnitOfWorkRepository> deletedEntities;
///<summary>
/// 实例化工作单元
///</summary>
public UnitOfWork()
{
this.addedEntities =new Dictionary<object,
IUnitOfWorkRepository>();
this.changedEntities =new Dictionary<object,
IUnitOfWorkRepository>();
this.deletedEntities =new Dictionary<object,
IUnitOfWorkRepository>();
}
#region IUnitOfWork 方法
///<summary>
/// 注册添加操作
///</summary>
///<param name="entity"></param>
///<param name="repository"></param>
publicvoid RegisterAdded(object entity, IUnitOfWorkRepository repository)
{
this.addedEntities.Add(entity, repository);
}
///<summary>
/// 注册更改操作
///</summary>
///<param name="entity"></param>
///<param name="repository"></param>
publicvoid RegisterChanged(object entity, IUnitOfWorkRepository repository)
{
this.changedEntities.Add(entity, repository);
}
///<summary>
/// 注册删除操作
///</summary>
///<param name="entity"></param>
///<param name="repository"></param>
publicvoid RegisterRemoved(object entity, IUnitOfWorkRepository repository)
{
this.deletedEntities.Add(entity, repository);
}
///<summary>
/// 执行内存列表保存的操作
///</summary>
publicvoid Commit()
{
using (TransactionScope scope =new TransactionScope())
{
foreach (object entity inthis.deletedEntities.Keys)
{
this.deletedEntities[entity].DeletedItem(entity);
}
foreach (object entity inthis.addedEntities.Keys)
{
this.addedEntities[entity].NewItem(entity);
}
foreach (object entity inthis.changedEntities.Keys)
{
this.changedEntities[entity].UpdatedItem(entity);
}
scope.Complete();
}
this.deletedEntities.Clear();
this.addedEntities.Clear();
this.changedEntities.Clear();
}
#endregion
}
}
框架都搭好之后 我们建一个TestRepository.cs 测试的仓储 继承IUnitOfWorkRepository
代码
using System.Collections.Generic;
namespace UnitOfWork
{
publicclass TestRepository : IUnitOfWorkRepository
{
private IUnitOfWork unitOfWork;
private IUnitOfWork TestUnitOfWork
{
get { returnthis.unitOfWork; }
}
public TestRepository(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
publicvoid Add(object _object)
{
TestUnitOfWork.RegisterAdded( _object,this);
Console.WriteLine("注册添加数据"+ _object);
}
publicvoid Delete(object _object)
{
TestUnitOfWork.RegisterRemoved(_object, this);
Console.WriteLine("注册删除数据"+ _object);
}
publicvoid update(object _object)
{
TestUnitOfWork.RegisterChanged(_object, this);
Console.WriteLine("注册更新数据"+ _object);
}
publicvoid NewItem(object _object)
{
Console.WriteLine("执行添加数据"+ _object);
}
publicvoid UpdatedItem(object _object)
{
Console.WriteLine("执行更新数据"+ _object);
}
publicvoid DeletedItem(object _object)
{
Console.WriteLine("执行删除数据"+ _object);
}
}
}
现在一切准备就绪 当然不能直接用仓储给外部调用 这里要添加个Server层
代码
using System.Collections.Generic;
namespace UnitOfWork
{
publicclass TestServer
{
privatestatic IUnitOfWork unitOfWork;
privatestatic TestRepository _TestRepository;
static TestServer()
{
TestServer.unitOfWork =new UnitOfWork();
_TestRepository =new TestRepository(unitOfWork);
}
publicstaticvoid Add()
{
_TestRepository.Add(1);
_TestRepository.Add(2);
_TestRepository.Add(3);
_TestRepository.Add(4);
_TestRepository.Add(5);
unitOfWork.Commit();
}
publicstaticvoid Add(object _object)
{
_TestRepository.Add(_object);
_TestRepository.Delete(_object);
_TestRepository.update(_object);
unitOfWork.Commit();
}
publicstaticvoid Delete(object _object)
{
_TestRepository.Delete(_object);
unitOfWork.Commit();
}
publicstaticvoid Update(object _object)
{
_TestRepository.update(_object);
unitOfWork.Commit();
}
}
}
这个是调用方式
代码
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnitOfWork;
namespace ConsoleApplication1
{
class Program
{
staticvoid Main(string[] args)
{
TestServer.Add(1);
Console.WriteLine("----------------------------");
TestServer.Add();
Console.Read();
}
}
}



浙公网安备 33010602011771号