前言

关于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的更多相关文章

  1. EF5中使用UnitOfWork

    前言 每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性.一致性. 解决办法是:在ObjectContext的CRUD操作基础上再包装一层,提供 ...

  2. 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...

  3. 2.EF中 Code-First 方式的数据库迁移

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...

  4. EF中扩展出Between操作符 (修订版)

    随手记录一下,这是针对原文错误的修改. 原文:EF中扩展出Between操作符 直接使用是错误的,修改后的扩展方法: /// <summary> /// 扩展 Between 操作符 // ...

  5. 如何在EF中实现left join(左联接)查询

    在EF中,当在dbset使用join关联多表查询时,连接查询的表如果没有建立相应的外键关系时,EF生成的SQL语句是inner join(内联),对于inner join,有所了解的同学都知道,很多时 ...

  6. EF中执行sql语句,以及事务

    EF to sql string sql = "select T_Task.BSID,T_Task.CloseDate,T_Task.CompleteDate,T_Task.CloseUse ...

  7. EF架构~在ef中支持IQueryable级别的Contains被翻译成了Exists,性能可以接受!

    回到目录 Entityframeworks很聪明 不错,非常不错!ef里的contains比linq to sql里的contains有了明显的提升,事实上,是在进行SQL语句翻译上有所提升,在lin ...

  8. DB表的关系及EF中Fluent API的使用

    现在使用多数的数据库是关系型数据库,那么表与表之间的关系就会显得尤其重要,对于数据的CRUD处理和以后数据的分析有很大的好处.下面是对于数据库中对表关系的理解以及在EF中使用Fluent API来创建 ...

  9. EF 中事务的书写

    在EF 中怎么使用事务? 这个问题纠结了我好久,直到有人跟我一起讨论,我和同事一起讨论查资料. 查的好多资料都是使用 using (TransactionScope scope = new Trans ...

随机推荐

  1. 15.java设计模式之访问者模式

    基本需求: 电脑需要键盘鼠标等固定的组件组成 现在分为个人,组织等去买电脑,而同一种组件对不同的人(访问者)做出不同的折扣,从而电脑的价格也不一样 传统的解决方法:在组件内部进行判断访问人的类型,从而 ...

  2. python办公入门4:xlrd操作excel行

    操作excel行 1 #通过索引获取操作行 2 sheet=data.sheet_by_index(0) 3 #获取当前sheet下的有效行数 4 print(sheet.nrows) 5 #获取某一 ...

  3. Java反射说得透彻一些

    目录 一.反射机制是什么? 二.反射的具体使用 2.1 获取对象的包名以及类名 2.2 获取Class对象 2.3 getInstance()获取指定类型的实例化对象 2.4 通过构造函数对象实例化对 ...

  4. kali putty远程连接允许以root身份登录

    原文链接:https://blog.csdn.net/long_long_chuang/article/details/70227874 kali linux通过ssh+putty来实现远程登录(亲测 ...

  5. 《高并发下的.NET》第2季 - 故障公告:高并发下全线崩溃

    大家好,非常抱歉,在昨天下午(12月3日)的访问高峰,园子迎来更高的并发,在这样的高并发下,突发的数据库连接故障造成博客站点全线崩溃,由此给您带来很大的麻烦,请您谅解. 最近,我们一边在忙于AWS合作 ...

  6. Spring Cloud Alibaba 初体验(六) Seata 及结合 MyBatis 与 MyBatis-Plus 的使用

    一.下载与运行 本文使用 Seata 1.1.0:https://github.com/seata/seata/releases Windows 环境下双击 bin/seata-server.bat ...

  7. 通过sql 语句将多行数据拼接到一行中

  8. jupyter notebook 将当前目录设置为工作目录

    生成配置文件首先打开你的CMD或者是终端(Linux),在你配置过环境变量的基础下,你直接输入以下命令: jupyter notebook --generate-config 然后打开生成的配置文件, ...

  9. Moviepy音视频开发:视频转gif动画或jpg图片exe图形化工具开发案例

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 老猿之所以学习和研究Moviepy的使用,是因为需要一个将视频转成动画的工具,当时在网上到处搜索查找免费使用工具,结果找了很多自称免费的工具,但转完 ...

  10. Python匹配对象的groups、groupdict和group之间的关系

    匹配对象的groups()方法返回一个包含所有参与匹配的子组(不含组0)的匹配到的搜索文本子串的元组,groupdict返回一个包含所有匹配到的命名组的组名为键值和命名组匹配到的搜索文本子串为值作为元 ...