封装自己的dapper lambda扩展-设计篇
前言
昨天开源了业务业余时间自己封装的dapper lambda扩展,同时写了篇博文《编写自己的dapper lambda扩展-使用篇》简单的介绍了下其使用,今天将分享下它的设计思路
链式编程
其实就是将多个方法通过点(.)将它们串接起来,让代码更加简洁, 可读性更强。
new SqlConnection("").QuerySet<User>()
.Where(a => a.Name == "aasdasd")
.OrderBy(a => a.CreateTime)
.Top(10)
.Select(a => a.Name).ToList();
其原理是类的调用方法的返回值类型为类本身或其基类,选择返回基类的原因是为了做降级约束,例如我希望使用了Top之后接着Select和ToList,无法再用where或orderBy。
UML图

原型代码
CommandSet
public class CommandSet<T> : IInsert<T>, ICommand<T>
{
#region 方法
public int Insert(T entity)
{
throw new NotImplementedException();
} public int Update(T entity)
{
throw new NotImplementedException();
} public int Update(Expression<Func<T, T>> updateExpression)
{
throw new NotImplementedException();
} public int Delete()
{
throw new NotImplementedException();
} public IInsert<T> IfNotExists(Expression<Func<T, bool>> predicate)
{
throw new NotImplementedException();
} public ICommand<T> Where(Expression<Func<T, bool>> predicate)
{
throw new NotImplementedException();
}
#endregion
} public interface ICommand<T>
{
int Update(T entity);
int Update(Expression<Func<T, T>> updateExpression);
int Delete();
} public interface IInsert<T>
{
int Insert(T entity);
} public static class Database
{
public static QuerySet<T> QuerySet<T>(this SqlConnection sqlConnection)
{
return new QuerySet<T>();
} public static CommandSet<T> CommandSet<T>(this SqlConnection sqlConnection)
{
return new CommandSet<T>();
}
}
QuerySet
public class QuerySet<T> : IAggregation<T>
{
#region 方法
public T Get()
{
throw new NotImplementedException();
} public List<T> ToList()
{
throw new NotImplementedException();
} public PageList<T> PageList(int pageIndex, int pageSize)
{
throw new NotImplementedException();
} public List<T> UpdateSelect(Expression<Func<T, T>> @where)
{
throw new NotImplementedException();
} public IQuery<TResult> Select<TResult>(Expression<Func<T, TResult>> selector)
{
throw new NotImplementedException();
} public IOption<T> Top(int num)
{
throw new NotImplementedException();
} public IOrder<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> field)
{
throw new NotImplementedException();
} public IOrder<T> OrderByDescing<TProperty>(Expression<Func<T, TProperty>> field)
{
throw new NotImplementedException();
} public int Count()
{
throw new NotImplementedException();
} public bool Exists()
{
throw new NotImplementedException();
} public QuerySet<T> Where(Expression<Func<T, bool>> predicate)
{
throw new NotImplementedException();
}
#endregion
} public interface IAggregation<T> : IOrder<T>
{
int Count();
bool Exists();
} public interface IOrder<T> : IOption<T>
{
IOrder<T> OrderBy<TProperty>(Expression<Func<T, TProperty>> field);
IOrder<T> OrderByDescing<TProperty>(Expression<Func<T, TProperty>> field);
} public interface IOption<T> : IQuery<T>, IUpdateSelect<T>
{
IQuery<TResult> Select<TResult>(Expression<Func<T, TResult>> selector); IOption<T> Top(int num);
} public interface IUpdateSelect<T>
{
List<T> UpdateSelect(Expression<Func<T, T>> where);
} public interface IQuery<T>
{
T Get(); List<T> ToList(); PageList<T> PageList(int pageIndex, int pageSize);
}
以上为基本的设计模型,具体实现如有问题可以查看我的源码。
表达式树的解析
具体实现的时候会涉及到很多的表达式树的解析,例如where条件、部分字段update,而我实现的时候一共两步:先修树,再翻译。然而无论哪步都得对表达式树进行遍历。
表达式树
百度的定义:也称为“表达式目录树”,以数据形式表示语言级代码,它是一种抽象语法树或者说是一种数据结构。
我对它的理解是,它本质是一个二叉树,节点拥有自己的属性像nodetype。
而它的遍历方式为前序遍历
前序遍历
百度的定义:历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树,以下图为例

其遍历结果为:ABDECF
以一个实际例子:

从上图可以看出,我们会先遍历到根节点的NodeType AndAlso翻译为 and ,然后到节点2,NodeType的Equal翻译为 = ,再到3节点翻译为 Name,再到4节点翻译为'skychen',那么将3、4节点拼接起来就为Name = 'skychen',如果类推6、7为Age >= 18,最后拼接这个语句为 Name = 'skychen' and Age >= 18。
修树
修树的目的,为了我们更好的翻译,例如DateTime.Now表达式树里的NodeType为MemberAccess,我希望转换成NodeType为Constant类型,以'2018-06-27 16:18:00'这个值作为翻译。
结束
以上为设计和实现的要点,具体的实现问题可以查看源码,如果有建议和疑问可以在下方留言,如果对您起到作用,希望您点一下推荐作为对我的支持。
再次双手奉上源码:https://github.com/SkyChenSky/Sikiro.DapperLambdaExtension.MsSql
封装自己的dapper lambda扩展-设计篇的更多相关文章
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- 编写自己的dapper lambda扩展-使用篇
前言 这是针对dapper的一个扩展,支持lambda表达式的写法,链式风格让开发者使用起来更加优雅.直观.现在暂时只有MsSql的扩展,也没有实现事务的写法,将会在后续的版本补充. 这是个人业余的开 ...
- 开源Dapper的Lambda扩展-Sikiro.Dapper.Extension V2.0
前言 去年我在业余时间,自己整了一套dapper的lambda表达式的封装,原本是作为了一个个人的娱乐项目,当时也只支持了Sql Server数据库.随之开源后,有不少朋友也对此做了试用,也对我这个项 ...
- 基于Dapper的开源Lambda扩展LnskyDB 2.0已支持多表查询
LnskyDB LnskyDB是基于Dapper的Lambda扩展,支持按时间分库分表,也可以自定义分库分表方法.而且可以T4生成实体类免去手写实体类的烦恼. 文档地址: https://lining ...
- 基于Dapper的开源Lambda扩展,且支持分库分表自动生成实体之基础介绍
LnskyDB LnskyDB是基于Dapper的Lambda扩展,支持按时间分库分表,也可以自定义分库分表方法.而且可以T4生成实体类免去手写实体类的烦恼. 文档地址: https://lining ...
- 基于Dapper的开源Lambda扩展LnskyDB 3.0已支持Mysql数据库
LnskyDB LnskyDB是基于Dapper的Lambda扩展,支持按时间分库分表,也可以自定义分库分表方法.而且可以T4生成实体类免去手写实体类的烦恼.,现在已经支持MySql和Sql serv ...
- 《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
1.简介 上一篇宏哥介绍了如何设计支持不同浏览器测试,宏哥的方法就是通过来切换配置文件设置的浏览器名称的值,来确定启动什么浏览器进行脚本测试.宏哥将这个叫做浏览器引擎类.这个类负责获取浏览器类型和启动 ...
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
- jQuery2.x源码解析(设计篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...
随机推荐
- (转载)解决NVIDIA显卡驱动“没有找到兼容的图形硬件”的问题
(转载)解决NVIDIA显卡驱动“没有找到兼容的图形硬件”的问题 原出处:http://www.cnblogs.com/longdouhzt/archive/2012/02/28/2370660.ht ...
- AIOps背景/所应具备技术能力分析(上)
本文篇幅较长,分为上,中,下,三个部分进行连载.内容分别为:AIOps 背景/所应具备技术能力分析(上),AIOps 常见的误解(中),挑战及建议(下). 前言 我大概是 5,6 年前开始接触 ITO ...
- Java-- String源码分析
版权声明:本文为博主原创文章,未经博主允许不得转载 本篇博文基于java8,主要探讨java中的String源码. 首先,将一个类分为几个部分,分别是类定义(继承,实现接口等),全局变量,方法,内部类 ...
- c#判断两个对象和对象中的属性是否相同(以及记录对象中的哪些字段,和详细的改变情况)
当前项目需要记录变更记录,即用户在进行编辑后,将变更操作记录下来.但是数据没有发生变化,则不记录. 代码1:(仅仅返回是否变化的标识) /// <summary> /// 反射对比实体属性 ...
- Error in Log_event::read_log_event(): 'Event too small', data_len: 0, event_type: 0
MySQL主从复制报错如下: 2018-04-11 09:11:16 2400 [Note] Slave SQL thread initialized, starting replication in ...
- Timeout occurred while waiting for latch: class 'ACCESS_METHODS_DATASET_PARENT'
前些天某个SQL Server数据库的错误日志爆出如下错误: Timeout occurred while waiting for latch: class 'ACCESS_METHODS_DATAS ...
- Python比较(关系)运算符
比较(关系)运算符 运 算 符 作 用 举 例 结 果 > 大于 'a'>'b' False < 小于 156<456 True == 等于 'c' ...
- android 休眠唤醒机制分析(一) — wake_lock【转】
Android的休眠唤醒主要基于wake_lock机制,只要系统中存在任一有效的wake_lock,系统就不能进入深度休眠,但可以进行设备的浅度休眠操作.wake_lock一般在关闭lcd.tp但系统 ...
- 用好lua+unity,让性能飞起来——luajit集成篇/平台相关篇
luajit集成篇 大家都知道luajit比原生lua快,快在jit这三个字上. 但实际情况是,luajit的行为十分复杂.尤其jit并不是一个简单的把代码翻译成机器码的机制,背后有很多会影响性能的因 ...
- 特别篇:Hyper-v群集模拟实战演示
介绍 由于前面几张的都是直接整理了下 九叔的hyper-v电子书发上来的,个人觉得他写的不是最详细,因此今天我按照自己的实际情况来写个模拟的实战演示.所有的东西都通过VMware WorkStatio ...