EF中使用UnitOfWork
前言
关于EF5中使用UnitWork,参见另一博文: https://www.cnblogs.com/masonblog/p/9801162.html
每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性、一致性。
解决办法是:在ObjectContext的CRUD操作基础上再包装一层,提供统一的入口,让服务层调用。
同一个UnitOfWork实例对象下所有的ObjectContext都共同一个数据库上下文对象(ps:EF用的是ObjectContext),也就是共用一个事物。
提交数据库时,只要有一个操作失败,那么所有的操作都被视为失败。
实际使用:https://www.cnblogs.com/masonblog/p/9563199.html
代码托管:https://github.com/catbiscuit/AutofacStudy
实现过程
实体层

删除其中的两个.tt文件,然后在edmx页面,右键点击属性,将属性中的代码生成策略 从"无"修改为"默认值"。

数据访问层

Teacher表示例
IDAL层
直接继承IDALBase<T>泛型接口,其中定义了一些基础的方法。
namespace Apps.IDAL
{
public interface ITeacherDAL : IDALBase<Teacher>
{
}
}
DAL层
直接继承DALBase<T>类,和ITeacherDAL接口。
DALBase类,需要提供实体类和数据库上下文。因为需要创建一个统一管理数据库操作的对象。
namespace Apps.DAL
{
public class TeacherDAL : DALBase<Teacher, AutofacDBEntities>, ITeacherDAL
{
public TeacherDAL(IDatabaseFactory<AutofacDBEntities> databaseFactory)
: base(databaseFactory)
{ }
}
}
IBLL层
定义基本的数据操作方法。
namespace Apps.IBLL
{
public interface ITeacherBLL
{
bool Add(Teacher entity); bool Delete(Teacher entity); bool Update(); Teacher GetModelByCondition(Expression<Func<Teacher, bool>> predicate); IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate,
Expression<Func<Teacher, object>> orderBy,
bool isAscending); IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate); Teacher GetModelBySql(string sql);
}
}
BLL层
对ITeacherBLL接口中方法的实现。
namespace Apps.BLL
{
public class TeacherBLL : ITeacherBLL
{
private readonly ITeacherDAL _iTeacherDAL;
private readonly IUnitOfWork<AutofacDBEntities> _uwork; public TeacherBLL(ITeacherDAL iTeacherDAL
, IUnitOfWork<AutofacDBEntities> uwork)
{
this._iTeacherDAL = iTeacherDAL;
this._uwork = uwork;
} public bool Add(Teacher entity)
{
_iTeacherDAL.Add(entity);
return _uwork.Commit() > 0;
}
public bool Delete(Teacher entity)
{
_iTeacherDAL.Delete(entity);
return _uwork.Commit() > 0;
} public bool Update()
{
return _uwork.Commit() > 0;
} public Teacher GetModelByCondition(Expression<Func<Teacher, bool>> predicate)
{
return _iTeacherDAL.GetModelByCondition(predicate);
} public IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate
, Expression<Func<Teacher, object>> orderBy
, bool isAscending)
{
return _iTeacherDAL.GetList(predicate, orderBy, isAscending);
} public IQueryable<Teacher> GetList(Expression<Func<Teacher, bool>> predicate)
{
return _iTeacherDAL.GetList(predicate);
} public Teacher GetModelBySql(string sql)
{
return _iTeacherDAL.GetModelBySql(sql);
}
}
}
注意
第一:类中定义了一个IUnitOfWork泛型对象,这个就是单元事务的管理对象。
DAL层只是将对数据的操作,添加到一个数据缓存的集合中。
当数据操作的步骤完成时,才调用IUnitOfWork泛型对象进行数据操作的提交。
这样确保了原子性和一致性。
第二:Update操作,BLL并没有将数据的操作添加到数据缓存的集合中。
此处,可以通过单步调试,当执行到UnitOfWork类中时,
监视DbContext对象的值,这个对象会监视数据库上下文中数据的状态。
这个地方,就要求Update操作的对象只能是从数据库获取得来。
使用lambda表达式获取实体。
示例操作:
Model model = DAL.GetModel(2);
model.Name = "修改Name";
BLL.Update();
此时BLL层执行update方法,实际上只是执行了单元事务的提交,也就完成了对该条记录的修改。
但是,如果是实例化的对象是无法修改数据。
Model model = new Model();
model.ID = 2;
model.Name = "修改Name";
BLL.Update();
这样执行更新操作,是无法修改数据的
总结
DAL层,只是将数据的操作(新增修改删除)附加到数据库上下文中。
UnitOfWork,才是将数据进行提交的地方。
所以,BLL层的方法才能实现对数据的完成操作。
EF中使用UnitOfWork的更多相关文章
- EF5中使用UnitOfWork
前言 每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性.一致性. 解决办法是:在ObjectContext的CRUD操作基础上再包装一层,提供 ...
- 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...
- 2.EF中 Code-First 方式的数据库迁移
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...
- EF中扩展出Between操作符 (修订版)
随手记录一下,这是针对原文错误的修改. 原文:EF中扩展出Between操作符 直接使用是错误的,修改后的扩展方法: /// <summary> /// 扩展 Between 操作符 // ...
- 如何在EF中实现left join(左联接)查询
在EF中,当在dbset使用join关联多表查询时,连接查询的表如果没有建立相应的外键关系时,EF生成的SQL语句是inner join(内联),对于inner join,有所了解的同学都知道,很多时 ...
- EF中执行sql语句,以及事务
EF to sql string sql = "select T_Task.BSID,T_Task.CloseDate,T_Task.CompleteDate,T_Task.CloseUse ...
- EF架构~在ef中支持IQueryable级别的Contains被翻译成了Exists,性能可以接受!
回到目录 Entityframeworks很聪明 不错,非常不错!ef里的contains比linq to sql里的contains有了明显的提升,事实上,是在进行SQL语句翻译上有所提升,在lin ...
- DB表的关系及EF中Fluent API的使用
现在使用多数的数据库是关系型数据库,那么表与表之间的关系就会显得尤其重要,对于数据的CRUD处理和以后数据的分析有很大的好处.下面是对于数据库中对表关系的理解以及在EF中使用Fluent API来创建 ...
- EF 中事务的书写
在EF 中怎么使用事务? 这个问题纠结了我好久,直到有人跟我一起讨论,我和同事一起讨论查资料. 查的好多资料都是使用 using (TransactionScope scope = new Trans ...
随机推荐
- Linux 学习笔记03丨Linux文件系统、文件基本属性、目录处理及文件查看
Chapter 2. 文件系统 2.1 Linux 系统目录结构 命令窗口下输入命令: $ ls /,能够看到根目录下的全部目录及文件 树状目录结构为: 最顶级的目录: / :根目录 / 是根目录,~ ...
- AtCoder Beginner Contest 178 E - Dist Max 题解(推公式)
题目链接 题目大意 给你n个点(n<=2e5)要你求所有点中两个点最短的曼哈顿距离 曼哈顿距离定义为d(i,j)=|x1-x2|+|y1-y2|. 题目思路 想了很久也没有什么思路,其实就是一个 ...
- IDEA创建web工程(超简单)
Idea创建Web工程 以新建模块为例. 新建Maven项目 勾选[Create from artchetype] 选择[org.apache.maven.archetypes:maven-arche ...
- 加快alter table
mysql的alter table操作的性能对打表来说是个大问题. mysql执行大部分修改表结构的方法是用新的结构创建一个空表,从旧表中查出所有的数据插入新表,然后删除旧表.这样操作就可能需要花费很 ...
- bootstrap 按钮颜色属性
bootstrap 按钮颜色属性有几种
- 面试官:说一下List排序方法
1. 前言 排序算是比较高频的面试题了,节前面试了的两家公司都有问到排序问题,整理后分享给大家(文末见总结). 通常我们想到实现排序就是 Collections 工具类的 sort() 方法,而 so ...
- (十八)面向流水线的设计:CPU的一心多用
一.单指令周期 由前可知,一条CPU指令的执行有三个步骤:指令读取.指令译码.指令执行.由于这个过程受CPU时钟的控制,如果我们将这个过程安排在一个CPU时钟周期内执行,这种设计思路就叫单 ...
- Synchronized和ReentTrantLock二者区别
写在前面 Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock.这两种锁以及后面提到 ...
- moviepy音视频剪辑:视频基类VideoClip子类VideoFileClip、CompositeVideoClip、ImageSequenceClip介绍
☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<moviepy音视频剪辑:moviepy中的剪辑相关类及关系>介绍了VideoClip主要有六个直接子类(VideoFileClip ...
- PyQt(Python+Qt)学习随笔:QTabWidget选项卡部件外观展示类属性elideMode、documentMode、tabBarAutoHide、tabShape介绍
QTabWidget的外观展示类属性包括tabPosition.tabShape.elideMode.usesScrollButtons.documentMode.tabBarAutoHide和ico ...