学习EF中看了网上很多关于Repository和UnitOfWork模式的教程,发现实现的方法有很多。个人任务UnitOfWork模式就是为了保证我们提交数据的完整性,起到事物的作用。其实EF本身就带这功能db.SaveChange();就可以实行了,只要我们保证同一个上下文中。只是我们单用EF来执行的时候可能会出现如下代码
using(DbContext db = new DbContext)
{
//---你要执行的相关操作
db.SaveChange();
}
那事实上我们会使用Repository来对实体类进行操作,如果每个Repository都有DbContext db = new DbContext那如何保证提交数据的完整性,这是就要使用UnitOfWork模式了,每个Repository是作为一个单元在工作,最后需要整个提交。
那其实我们只需要每个Repository的上下文一致就行了
方法1.
使用CallContext从访问的线程中取上下文以确保一致
我们每个请求都去CallContext中判断下有就直接去,没有就创建上下文
/// <summary>
/// 用来创建EF上下文对象,且保证线程内唯一。
/// </summary>
public class DbContextFactory
{
//DbContext在System.Data.Entity;中,不过这里直接只引用这一个不行,还有EF其他的一些NameSpace所以直接添加一个实体模型,所有引用都进来了,然后再把模型删了
public static DbContext GetDbContext()
{
DbContext dbContext = (DbContext)CallContext.GetData("dbContext");
if (dbContext == null)
{
dbContext = new WebEntities();
CallContext.SetData("dbContext", dbContext);
}
return dbContext;
}
这样只要每个Repository的上下文都通过DbContextFactory来获取就能确保每个请求的上下文一致了。这样一来好像我们的UnitOfWork类其实没多大作用,无非就是通过DbContextFactory获取到上下文然后进行下SaveChange()就完事了哦。这样就搞定了UnirOfWork模式吗,我还是比较有疑问的???
方法2.
通过UnitOfWork类来产生Repository,也就是说Repository是根据UnitOfWork的上下文来生成的,这样确保一致性。
a.https://www.cnblogs.com/Leo_wl/p/4204519.html
b.https://www.cnblogs.com/Ray-liang/p/3809822.html
或者我的还有篇https://blog.csdn.net/sammy520/article/details/79310864这是我参考了上述b的实现方法自己尝试做了一遍整理的笔记。
可以参考下这两几篇文章的方法,实现的方式可能不一样,但是原理其实差不多。我目前就是借鉴他们的方法来实现的。不过我有疑问的是,我的UnitOfWork的上下文是通过CallContext来获取的,那其实我只要让我的Repository产生根据CallContext来获取上下文生成也就回归的方法1中去了。好像这样做有点绕远路了,呵呵!不过这样做好处还是有的,因为Repository的上下文是根据UnitOfWork来生成的,那UnitOfWork可以根据CallContext来也可以自己new一个都能保证此UnitOfWork下的Repository的一致性。
上述a,b两个通过UnitOfWork实现的方法 都是通过定义了
private IDictionary<Type, object> RepositoryDic = new Dictionary<Type, object>();来将Repository存入字典中,需要时取来用。
只是a采用的是通过UnitOfWork产生一个Repository后进行操作
var empRepository = this.uow.Repository<emp>();
emp model = new emp();
model.empid = "001";
model.empname="jhon";
empRepository.add(model);
uow.Commit();
而b时直接将Reposotory的方法通过UnitOfWork来实现了一遍,因此代码也有所改变
emp model = new emp();
model.empid = "001";
model.empname="jhon";
uow.add<emp>(model);
uow.Commit();
可能下面的代码更简洁点,具体采用哪种方法看个人喜好了啊。