[开源]Dapper Repository 一种实现方式
- 接着上篇[开源]Entity Framework 6 Repository 一种实现方式
- 由于Dapper 本身就是轻量级Orm特性,这里参考Creating a Data Repository using Dapper dynamic queries in dapper 代码,来解决实体类与Expression<Func<T, bool>> predicate问题;
- 您可以通过Nuget:Install-Package MasterChief.DotNet.Core.Dapper;
- 您可以通过GitHub:MasterChief 查看具体源码以及单元测试;
- 欢迎Star,欢迎Issues;
插播一条求职
- 小弟拥有多年C#开发经验,从事过路灯,消防平台物联网平台开发,坐标上海;
- 如果贵司在招聘,烦请大佬考虑下,联系邮箱:MeetYan@outlook.com;
基于Dapper 的Repository实现
public abstract class DapperDbContextBase : IDbContext
{
#region Constructors
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectString">连接字符串</param>
protected DapperDbContextBase(string connectString)
{
ConnectString = connectString;
}
#endregion Constructors
#region Properties
/// <summary>
/// 获取 是否开启事务提交
/// </summary>
public IDbTransaction CurrentTransaction { get; private set; }
#endregion Properties
#region Fields
/// <summary>
/// 当前数据库连接
/// </summary>
public IDbConnection CurrentConnection =>
TransactionEnabled ? CurrentTransaction.Connection : CreateConnection();
/// <summary>
/// 获取 是否开启事务提交
/// </summary>
public bool TransactionEnabled => CurrentTransaction != null;
/// <summary>
/// 连接字符串
/// </summary>
protected readonly string ConnectString;
#endregion Fields
#region Methods
/// <summary>
/// 显式开启数据上下文事务
/// </summary>
/// <param name="isolationLevel">指定连接的事务锁定行为</param>
public void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
{
if (!TransactionEnabled) CurrentTransaction = CreateConnection().BeginTransaction(isolationLevel);
}
/// <summary>
/// 提交当前上下文的事务更改
/// </summary>
/// <exception cref="DataAccessException">提交数据更新时发生异常:" + msg</exception>
public void Commit()
{
if (TransactionEnabled)
try
{
CurrentTransaction.Commit();
}
catch (Exception ex)
{
if (ex.InnerException?.InnerException is SqlException sqlEx)
{
var msg = DataBaseHelper.GetSqlExceptionMessage(sqlEx.Number);
throw new DataAccessException("提交数据更新时发生异常:" + msg, sqlEx);
}
throw;
}
}
/// <summary>
/// 创建记录
/// </summary>
/// <param name="entity">需要操作的实体类</param>
/// <returns>操作是否成功</returns>
public bool Create<T>(T entity)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(entity, "需要新增的数据记录");
// insert single data always return 0 but the data is inserted in database successfully
//https://github.com/StackExchange/Dapper/issues/587
//List<T> data = new List<T>() { entity };
return CurrentConnection.Insert(new List<T> {entity}, CurrentTransaction) > 0;
#region 测试代码
//string sql = @"INSERT INTO [dbo].[EFSample]
// ([ID]
// ,[CreateTime]
// ,[ModifyTime]
// ,[Available]
// ,[UserName])
//VALUES
// (@ID
// ,@CreateTime
// ,@ModifyTime
// ,@Available
// ,@UserName)";
//return CurrentConnection.Execute(sql, entity) > 0;
#endregion 测试代码
}
/// <summary>
/// 创建数据库连接IDbConnection
/// </summary>
/// <returns></returns>
public abstract IDbConnection CreateConnection();
/// <summary>
/// 删除记录
/// </summary>
/// <returns>操作是否成功</returns>
/// <param name="entity">需要操作的实体类.</param>
public bool Delete<T>(T entity)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(entity, "需要删除的数据记录");
return CurrentConnection.Delete(entity);
}
/// <summary>
/// 执行与释放或重置非托管资源关联的应用程序定义的任务。
/// </summary>
public void Dispose()
{
if (CurrentTransaction != null)
{
CurrentTransaction.Dispose();
CurrentTransaction = null;
}
CurrentConnection?.Dispose();
}
/// <summary>
/// 条件判断是否存在
/// </summary>
/// <returns>是否存在</returns>
/// <param name="predicate">判断条件委托</param>
public bool Exist<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
var tableName = GetTableName<T>();
var queryResult = DynamicQuery.GetDynamicQuery(tableName, predicate);
var result =
CurrentConnection.ExecuteScalar(queryResult.Sql, (object) queryResult.Param, CurrentTransaction);
return result != null;
}
/// <summary>
/// 根据id获取记录
/// </summary>
/// <returns>记录</returns>
/// <param name="id">id.</param>
public T GetByKeyId<T>(object id)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(id, "Id");
return CurrentConnection.Get<T>(id, CurrentTransaction);
}
/// <summary>
/// 条件获取记录集合
/// </summary>
/// <returns>集合</returns>
/// <param name="predicate">筛选条件.</param>
public List<T> GetList<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
var tableName = GetTableName<T>();
var queryResult = DynamicQuery.GetDynamicQuery(tableName, predicate);
return CurrentConnection.Query<T>(queryResult.Sql, (object) queryResult.Param, CurrentTransaction).ToList();
}
/// <summary>
/// 条件获取记录第一条或者默认
/// </summary>
/// <returns>记录</returns>
/// <param name="predicate">筛选条件.</param>
public T GetFirstOrDefault<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
var tableName = GetTableName<T>();
var queryResult = DynamicQuery.GetDynamicQuery(tableName, predicate);
return CurrentConnection.QueryFirst<T>(queryResult.Sql, (object) queryResult.Param, CurrentTransaction);
}
/// <summary>
/// 条件查询
/// </summary>
/// <returns>IQueryable</returns>
/// <param name="predicate">筛选条件.</param>
public IQueryable<T> Query<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
throw new NotImplementedException();
}
/// <summary>
/// 显式回滚事务,仅在显式开启事务后有用
/// </summary>
public void Rollback()
{
if (TransactionEnabled) CurrentTransaction.Rollback();
}
/// <summary>
/// 执行Sql 脚本查询
/// </summary>
/// <param name="sql">Sql语句</param>
/// <param name="parameters">参数</param>
/// <returns>集合</returns>
public IEnumerable<T> SqlQuery<T>(string sql, IDbDataParameter[] parameters)
{
ValidateOperator.Begin()
.NotNullOrEmpty(sql, "Sql语句");
var dataParameters = CreateParameter(parameters);
return CurrentConnection.Query<T>(sql, dataParameters, CurrentTransaction);
}
/// <summary>
/// 根据记录
/// </summary>
/// <returns>操作是否成功.</returns>
/// <param name="entity">实体类记录.</param>
public bool Update<T>(T entity)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(entity, "需要更新的数据记录");
return CurrentConnection.Update(entity, CurrentTransaction);
}
private DapperParameter CreateParameter(IDbDataParameter[] parameters)
{
if (!(parameters?.Any() ?? false)) return null;
var dataParameters = new DapperParameter();
foreach (var parameter in parameters) dataParameters.Add(parameter);
return dataParameters;
}
private string GetTableName<T>()
where T : ModelBase
{
var tableCfgInfo = AttributeHelper.Get<T, TableAttribute>();
return tableCfgInfo != null ? tableCfgInfo.Name.Trim() : typeof(T).Name;
}
#endregion Methods
}
使用方法
public class SampleService : ISampleService
{
private readonly IDatabaseContextFactory _contextFactory;
public SampleService(IDatabaseContextFactory contextFactory)
{
_contextFactory = contextFactory;
}
/// <summary>
/// 创建
/// </summary>
/// <param name="sample">EFSample</param>
/// <returns></returns>
public bool Create(EfSample sample)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Create(sample);
}
}
/// <summary>
/// 条件查询
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public EfSample GetFirstOrDefault(Expression<Func<EfSample, bool>> predicate = null)
{
using (IDbContext context = _contextFactory.Create())
{
return context.GetFirstOrDefault(predicate);
}
}
/// <summary>
/// 根据主键查询
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public EfSample GetByKeyId(Guid id)
{
using (IDbContext context = _contextFactory.Create())
{
return context.GetByKeyId<EfSample>(id);
}
}
/// <summary>
/// 条件查询集合
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
public List<EfSample> GetList(Expression<Func<EfSample, bool>> predicate = null)
{
using (IDbContext context = _contextFactory.Create())
{
return context.GetList(predicate);
}
}
/// <summary>
/// 添加判断是否存在
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
public bool Exist(Expression<Func<EfSample, bool>> predicate = null)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Exist(predicate);
}
}
/// <summary>
/// 脚本查询
/// </summary>
/// <param name="sql">The SQL.</param>
/// <param name="parameter">DbParameter[]</param>
/// <returns></returns>
public List<EfSample> SqlQuery(string sql, DbParameter[] parameter)
{
using (IDbContext context = _contextFactory.Create())
{
return context.SqlQuery<EfSample>(sql, parameter)?.ToList();
}
}
/// <summary>
/// 更新
/// </summary>
/// <param name="sample">The sample.</param>
/// <returns></returns>
public bool Update(EfSample sample)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Update(sample);
}
}
/// <summary>
/// 事务
/// </summary>
/// <param name="sample">The sample.</param>
/// <param name="sample2">The sample2.</param>
/// <returns></returns>
public bool CreateWithTransaction(EfSample sample, EfSample sample2)
{
bool result;
using (IDbContext context = _contextFactory.Create())
{
try
{
context.BeginTransaction();//开启事务
context.Create(sample);
context.Create(sample2);
context.Commit();
result = true;
}
catch (Exception)
{
context.Rollback();
result = false;
}
}
return result;
}
/// <summary>
/// 删除
/// </summary>
/// <param name="sample"></param>
/// <returns></returns>
public bool Delete(EfSample sample)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Delete(sample);
}
}
}
结语
- Dapper与Entity Framework都是通过IRepository实现,所以您可以通过Ioc切换;
- 该篇的单元测试写法与上篇一致;
- 小弟不才,大佬轻拍;
[开源]Dapper Repository 一种实现方式的更多相关文章
- [开源]Entity Framework 6 Repository 一种实现方式
在使用Entity Framework这种ORM框架得时候,一般结合Repository仓储形式来处理业务逻辑:虽然这种模式带来很多好处,但是也会引发一些争议,在此抛开不谈,小弟结合项目经验来实现一下 ...
- Storm 学习之路(六)—— Storm项目三种打包方式对比分析
一.简介 在将Storm Topology提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任何插 ...
- Storm 系列(六)—— Storm 项目三种打包方式对比分析
一.简介 在将 Storm Topology 提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任 ...
- Web负载均衡的几种实现方式
Web负载均衡的几种实现方式摘要:负载均衡(Load Balance)是集群技术(Cluster)的一种应用.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用是 ...
- LVS三种工作方式八种算法
一.集群简介 什么是集群 计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一台计算机.集群系统中的单个计算 ...
- LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法)
一.集群简介 什么是集群 计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一 台计算机.集群系统中的单个计 ...
- WEB安全实战(五)XSS 攻击的第二种解决方式(推荐)
序 说到 XSS 攻击,前边已经有两篇文章在讲这个事了,这次又拿出来说,主要是针对近期工作中的一些新的问题.那么之前是怎么解决问题的呢?为什么又要换解决方式?以下就具体的跟大家分享一下. 旧方案 公司 ...
- Android平台中实现对XML的三种解析方式
本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...
- spring 整合 mybatis 中数据源的几种配置方式
因为spring 整合mybatis的过程中, 有好几种整合方式,尤其是数据源那块,经常看到不一样的配置方式,总感觉有点乱,所以今天有空总结下. 一.采用org.mybatis.spring.mapp ...
随机推荐
- BZOJ_2141_排队_树状数组+分块
BZOJ2141_排队_树状数组+分块 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了 ...
- linux命令----查看磁盘空间
今天用“web发布平台”发布测试的服务,两个节点中发现有一个节点没有发布成功,压测TPS始终上不去,排查后发现只有一个节点在打日志,另一个节点的服务进程都没有在运行,由此断定应该是没有发布成功,有点坑 ...
- 轻量级.Net Core服务注册工具CodeDi发布啦
为什么做这么一个工具 因为我们的系统往往时面向接口编程的,所以在开发Asp .net core项目的时候,一定会有大量大接口及其对应的实现要在ConfigureService注册到ServiceCol ...
- 【原】javascript笔记之this用法
javascript中的this学习起来相对复杂,最近花了点时间研究,总结起来大概这只有5种情况,相信只要熟悉这5种用法,基本是可以解决所有的this问题,文本不介绍this设计原理,只介绍用法,阅读 ...
- 基于CNN的人群密度图估计方法简述
人群计数的方法分为传统的视频和图像人群计数算法以及基于深度学习的人群计数算法,深度学习方法由于能够方便高效地提取高层特征而获得优越的性能是传统方法无法比拟的.本文简单了秒速了近几年,基于单张图像利用C ...
- 深度学习之Numpy整理
一.Numpy介绍.为什么要用Numpy 1.Numpy介绍 Numpy是Python的一个扩展包,语法和Matlab有很多相似之处.它支持高维数组和矩阵运算,也提供了许多数组和矩阵运算的函数.另外, ...
- Hystix熔断解决雪崩问题
1.线程隔离,服务降级(服务的消费方做降级处理) 当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果. 这就好比去买鱼,平常超市买鱼会 ...
- 【译】在C#中实现单例模式
目录 介绍 第一个版本 --不是线程安全的 第二个版本 -- 简单的线程安全 第三个版本 - 使用双重检查锁定尝试线程安全 第四个版本 - 不太懒,不使用锁且线程安全 第五版 - 完全懒惰的实例化 第 ...
- 设计模式之结构类模式PK
结构类模式包括: 适配器模式 桥梁模式 组合模式 装饰模式 门面模式 享元模式 代理模式 结构类模式着重于如何建立一个软件结构 为什么叫结构类模式呢? 因为他们都是通过组合类或对象产生更大结构以适应更 ...
- arcgis api 3.x for js 地图加载多个 SHP 图层压缩以及 json 文件展示(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...