前言

关于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. 牛客练习赛71 数学考试 题解(dp)

    题目链接 题目大意 要你求出有多少个长度为n的排列满足m个限制条件 第i个限制条件 p[i]表示前 p[i]个数不能是1-p[i]的排列 题目思路 这个感觉是dp但是不知道怎么dp 首先就是要明白如果 ...

  2. transform的2D和3D变换

    transform取值 none:默认值,即是无转换 matrix(,,,,,): 以一个含六值的(a,b,c,d,e,f)变换矩阵的形式指定一个2D变换,相当于直接应用一个[a,b,c,d,e,f] ...

  3. redis 做分布式锁

    ok 我们从最基础的一步步来 加锁: 1.setNx没有expire,拿锁线程挂掉后,死锁 2.setNx然后exipre分两步做,setNx后redis宕机,或者线程挂掉,死锁 3.SETNX re ...

  4. Jmeter-BeanShell断言的运用一(JSON响应数据与数据库比对)

    前言 最近在学习BeanShell断言,发现有点强大哈,只要会写代码,就没有什么是断言不了的,哈哈哈,不过我现在只会写点蹩脚的代码,下面将介绍下如何将返回的JSON数据与数据库数据做对比. 注:本次涉 ...

  5. CentOS 使用文件增加Swap空间

    使用硬盘文件增加swap空间 ///创建文件 dd if=/dev/zero of=/SWAP/swapfile bs=1M count=1000 ///格式化 mkswap /SWAP/swapfi ...

  6. web自动化-绕过登录

    两个方法: 1.常用的方法: 第一种方法是登录后查看网站的 cookie,请求 url 的时候把 cookie 带上(缺点是:cookie有时间限制.优点:简单,方便) 2.添加cookies的方式: ...

  7. Spring Cloud Alibaba 初体验(三) Nacos 与 Dubbo 集成

    一.新建项目 新建项目,只放置接口,用于暴露 Dubbo 服务接口 public interface GreetingService { String greeting(); } 二.provider ...

  8. Cys_Control(五) MMenu

    一.查看Menu原样式 1.通过Blend查看Menu原有样式 Menu的原有样式结构较为简单,由边框Border及集合控件 ItemsPresenter 组成,原有样式如下 <Style x: ...

  9. redis分布式锁解决超卖问题

    redis事务 redis事务介绍:    1. redis事务可以一次执行多个命令,本质是一组命令的集合. 2.一个事务中的所有命令都会序列化,按顺序串行化的执行而不会被其他命令插入 作用:一个队列 ...

  10. Django使用联合主键

    今天闲着没事,突然想起一个以前遇到的一个小问题.一直忘了来验证自己的解决方案,所以今天特意来查询了些资料来验证下自己的想法.整理如下: 单张表内建立联合主键: class IotTemp(models ...