接上文 项目架构开发:数据访问层之IQuery

本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务,

数据CUD每次都是立即执行的,这样有一些不好的地方,比如数据访问次数会增多,一笔数据的完整性无法保证

比如:批量新增2条记录,只有一条成功,这样的情况就应该Rollback;可能有人已经想到用数据库自带的事务保证完整性

虽然是可以,但是这样就不可避免地在业务层耦合SqlTransaction,我不想这种情况出现;

所以我们用windows自带的分布式事务TransactionScope来实现,TransactionScope可以实现多个数据库的事务锁,这点就比SqlTransaction强一些

当然我了解到分布式事务是不一般的复杂的,那些更好的处理方式我还没有掌握,所以先这么写吧,有这方面经验的朋友欢迎提建议

IUnitOfWork.cs

     public interface IUnitOfWork<T> where T : class
{
void RegisterAdd(T entity, Action callback);
void RegisterUpdate(T entity, Action callback);
void RegisterDelete(T entity, Action callback);
void Commit();
}

注册新增操作:RegisterAdd

注册更新操作:RegisterUpdate

注册修改操作:RegisterDelete

提交数据:Commit

工作单元的实现

 public class UnitOfWork<T> : IUnitOfWork<T> where T : class
{
private Dictionary<T, Action> addEntities;
private Dictionary<T, Action> updateEntities;
private Dictionary<T, Action> deleteEntities; public UnitOfWork()
{
addEntities = new Dictionary<T, Action>();
updateEntities = new Dictionary<T, Action>();
deleteEntities = new Dictionary<T, Action>();
} public void RegisterAdd(T entity, Action callback)
{
this.addEntities.Add(entity, callback);
} public void RegisterUpdate(T entity, Action callback)
{
this.updateEntities.Add(entity, callback);
} public void RegisterDelete(T entity, Action callback)
{
this.deleteEntities.Add(entity, callback);
} public void Commit()
{
using (TransactionScope scope = new TransactionScope())
{
foreach (var entity in deleteEntities.Keys)
{
this.deleteEntities[entity]();
} foreach (var entity in updateEntities.Keys)
{
this.updateEntities[entity]();
} foreach (var entity in addEntities.Keys)
{
this.addEntities[entity]();
} scope.Complete();
}
}
}

这里我们用了Action,这个是无返回值委托方法,如果大家需要返回值可以用Func

实现我们还是用DapperRepository,修改一下。在新增方法中注册数据持久化方法

好了,现在我们来看看测试结果

测试工作单元

还是用原来那个DapperRepositoryTest

我们修改一下实现过程:

单个新增

批量新增

运行结果

我们把表结构改一下,名称改成不能为null

AddBatch也要修改,正常的执行结果一个是抛出异常

         [TestMethod]
public void AddBatch()
{
try
{
var loginUser1 = new LoginUser()
{
Id = Guid.NewGuid(),
LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
Password = "mima1987",
IsEnabled = ,
CreateTime = DateTime.Now
}; var loginUser2 = new LoginUser()
{
Id = Guid.NewGuid(),
//LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
Password = "mima1987",
IsEnabled = ,
CreateTime = DateTime.Now
}; var list = new List<LoginUser>();
list.Add(loginUser1);
list.Add(loginUser2); repository.AddBatch(list);
unitOfWork.Commit();
}
catch (Exception ex)
{
var err = ex.Message;
} //long count = repository.Count(t => t.LoginName.In(new string[] { loginUser1.LoginName, loginUser2.LoginName })); //Assert.AreEqual(true, count >0);
}

运行看看

如期运行,到这里,工作单元就讲完了

完整项目架构

我们来看看完整的数据访问层架构

整个数据访问层就讲完了,虽然有些简陋,但是基本功能都有了

项目架构开发系列

项目架构开发:数据访问层之UnitOfWork的更多相关文章

  1. 项目架构开发:数据访问层之UnitOfWork (补充)

    应lisansi同学回复(项目架构开发:数据访问层之UnitOfWork)要求,补上Dapper的DbContext实现 using Dapper.Contrib.Extensions; using ...

  2. 企业级应用架构(三)三层架构之数据访问层的改进以及测试DOM的发布

    在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层能够支持一切数据访问技术,如Ado.n ...

  3. 项目架构开发:数据访问层之Cache

    数据访问层简单介绍 数据访问层,提供整个项目的数据访问与持久化功能.在分层系统中所有有关数据访问.检索.持久化的任务,最终都将在这一层完成. 来看一个比较经典的数据访问层结构图 大概可以看出如下信息 ...

  4. 项目架构开发:数据访问层之Logger

    接上文 项目架构开发:数据访问层之Cache 本章我们继续ILogger的开发 ILogger.cs public interface ILogger { void Info(object messa ...

  5. 项目架构开发:数据访问层之Repository

    接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪仓储”, 这个仓储只实现单表的CURD ...

  6. 项目架构开发:数据访问层之Query

    接上文 项目架构开发:数据访问层之Repository 上一章我们讲了IRepository接口,这张我们来讲IQuery 根据字面意思就可以知道,这次主要讲数据查询,上一章我们只针对单表做了查询的操 ...

  7. 随机获得MySQL数据库中100条数据方法 驾照题库项目 MVC架构 biz业务层的实现类 根据考试类型rand或order通过dao数据访问层接口得到数据库中100或全部数据

    package com.swift.jztk.biz; import java.util.Collections; import java.util.Comparator; import java.u ...

  8. 数据访问层之Repository

    数据访问层之Repository   接上文 项目架构开发:数据访问层之Logger 本章我们继续IRepository开发,这个仓储与领域模式里边的仓储有区别,更像一个工具类,也就是有些园友说的“伪 ...

  9. asp.net/wingtip/创建数据访问层

    一. 什么是数据访问层 在wingtip项目中,数据访问层是对以下三者的总称:1. product类等数据相关的实体类(class)2. 数据库(database),对实体类成员的存储3. 上述二者的 ...

随机推荐

  1. 最多两次股票交易-Best Time to Buy and Sell Stock III

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  2. WinAPI: GetClassName - 获取指定窗口的类名

    WinAPI: GetClassName - 获取指定窗口的类名 //声明: GetClassName( hWnd: HWND; {指定窗口句柄} lpClassName: PChar; {缓冲区} ...

  3. Java 页面的工具包

    所谓工具包,是指把页面的功能划分出来,放到另外一个包里面.方面工程管理.结构清晰.团队协作等. 根据原来的例子:要做一个com.myweb包的工具包com.myweb.tool 为导航栏统一创建接口 ...

  4. Linux系统监控命令

    1. uptime: 负载监控,w命令更好地显示当前登录用户数的信息 2.top: 相当于uptime,提供了负载平均值的快照 (1)第一行: up 48days: 系统运行时间 2 users: 当 ...

  5. 如何做到Zero Downtime重启Go服务?

    graceful的实践 使用endless库来实现,比如接入gin: r := gin.Default() r.GET("/", index) endless.ListenAndS ...

  6. Android中的IPC机制

    Android IPC简介 IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程.那么什么是进程,什么是线程,进程 ...

  7. ubuntu14.04下手动安装eclipse

    ubuntu14.04下手动安装eclipse 第一步: 安装jdk 第二步: 下载eclipse,假设下载的文件文件名为eclipse.tar.gz 第三步: 解压 sudo -zxvf ./ecl ...

  8. 法国总统放大招,用“分身术”竞选总统 全息3d 网

    编辑:大熊 [摘要]法国总统采用全息技术实现"分身"演讲,可谓是一次演讲,全面覆盖! 全息3d网讯:众所周知,欧美国家的总统是通过公开竞选得到的,所以能更直接.更广泛的近距离接触民 ...

  9. Extjs学习笔记之九 数据模型(上)-extjs

    来源:niutuku.com | vincent上传于2012-07-20 | 1802次浏览 | 0条评论 本文开始进入Extjs最核心最优秀的部分. 标签:Extjs 数据模型   Extjs的数 ...

  10. swift 2.0 用代码写一个简单地UIWebView

    其实写一个UIWebView 挺简单的,但是今天就被9.0 的新特性给坑了,不知道上一个项目中有没有遇到这个问题,反正是时间成了,自己也忘记了.今天还是再说一次吧. 我们先简单的创建一个UIWebVi ...