摘要:工作单元是命令模式得一种具体应用,就以webapi操作数据库来说工作单元模式,一次请求,需要操作多个或多次操作数据库,如果每操作一次都直接提交给数据库,那有可能在某些瞬态错误导致没法完成所有操作而产生数据不一致,不考虑分布式事务,最好得做法就是把所有操作打包,最后一次性把操作提交给数据库,这样可以最大程度保证一致性。设计模式Github源码
下面我们拿redis操作来描述一个工作单元
Repository(仓储类):这是用来写操作命令的库
UnitOfWork(工作单元类):里边有一个委托List 用来存储仓储类的命令,凡是你在进程里调用的Repository的方法都会存储在此,这个类还有一个执行方法Save,就是最终一起执行所有命令的方法
工作单元除了有以上有点,还有其他方面的优点,例如:
你在 UnitOfWork Save()方法里可以把你想在提交redis之前执行的其他需要统一执行的方法也写在上面,比如设置公共key,过滤命令之类的,怎么样,是不是和aop编程就搭边了,分离了操作命令与持久化,让它们自成模块,可以抽象通用的Save接口,具体实现可以是各种数据库,这样切换数据库也能使原来的操作不用修改(当然要支持sql语句的,例如很多ORM也是使用这种方式)
but,不能仅仅说优点,在数据库持久化使用这种设计的缺点(我认为的)还是有的,比如你在设计数据库仓储时候你用这个设计方案,就没法执行完一条sql得到结果后拿这个结果来去做其他事情,好比如你主键是自增的,你想执行完sql拿到插入后的id,这种就没得办法了,因为这些命令是save时候才执行的,所以一般都会两套走起。
代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace UnitOfWork
{
public class Model
{
public static Model CreateNew(string myKey)
{
return new Model()
{
Key = myKey
};
}
public string Key { get; set; }
}
public class Repository
{
public string Add(Model model)
{
Console.WriteLine(model.Key);
return "add command";
}
public string Update(Model model)
{
Console.WriteLine(model.Key);
return "update command";
}
public string Delete(Model model)
{
Console.WriteLine(model.Key);
return "delete command";
}
}
public class UnitOfWork
{
public List<Func<string, string>> Commands { get; set; } = new List<Func<string, string>>();
public void AddCommand(Func<string, string> repositoryFunc)
{
Commands.Add(repositoryFunc);
}
public void Save()
{
var publicKey = "PublicKey-";
//执行委托集合命令
var commandList = Commands.Select(c => c(publicKey)).ToList();
//打包redis命令然后提交
//code...
}
}
class Program
{
static void Main(string[] args)
{
UnitOfWork uow = new UnitOfWork();
Repository repository = new Repository();
uow.AddCommand((publicKey) =>
{
var model = Model.CreateNew(publicKey + "AddKey");
return repository.Add(model);
});
uow.AddCommand((publicKey) =>
{
var model = Model.CreateNew(publicKey + "UpdateKey");
return repository.Update(model);
});
uow.AddCommand((publicKey) =>
{
var model = Model.CreateNew(publicKey + "DeleteKey");
return repository.Delete(model);
});
Console.WriteLine("Hello World!");
//到这里才把所有语句执行
uow.Save();
Console.ReadKey();
}
}
}