专栏首页.NET技术封装自己的dapper lambda扩展-设计篇

封装自己的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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Visual Studio Package 插件开发之自动生成实体工具

      这一篇是VS插件基于Visual Studio SDK扩展开发的,可能有些朋友看到【生成实体】心里可能会暗想,T4模板都可以做了、动软不是已经做了么、不就是...

    陈珙
  • UML类图

      这几天回顾了《大话设计模式》,发现看类图的时候分不清了,为了加强记忆,也方便回顾,自己手动画了一次类图,并参考了网上文章将此作为笔记,记录下来。

    陈珙
  • 表达式树的解析.

    公司的orm框架在dapper的基础上扩展了一套表达式的方法,当时就研究了一下,把学习过程和结果记录下来,和大家分享。

    陈珙
  • java应用CAS

      CAS(Compare and Swap),即比较并替换。jdk里的大量源码通过CAS来提供线程安全操作,比如AtomicInteger类。下面我们来分析一...

    良辰美景TT
  • Android使用观察者模式Observer实现网络状态监听

    在Android开发过程中,很多时候都会用到当前网络的状态判断以及网络状况发生变化的时候做出相应的反应,要想监听网络状态,用观察者模式再合适不过了,废话不多说,...

    砸漏
  • JAVA虚拟机关闭钩子(Shutdown Hook)

    当你认真的去看一个组件的源码的时候,你会经常看见这种关闭钩子的函数,如果你不了解的话,谷歌一下,你就会发现如下文章就是搜索引擎出来的第一篇,不愧是出自我们优秀的...

    zhisheng
  • Android 单元测试 Robolectric

    通过实现一套 JVM 能够运行的 Android 代码,从而实现脱离 Android 环境进行测试。

    七适散人
  • Android架构组件Room的使用详解

    Room其实就是一个orm,抽象了SQLite的使用,但是它作为Android的亲儿子orm,并且原生支持LiveData和Rxjava嵌套使用,学习一下还是不...

    砸漏
  • Java 接口

    但如果三角形类不需要draw()方法,只能去掉图形类中的draw()或把draw()变成图形类私有

    用户2965768
  • 桥接模式

    概述 当一个抽象对象可能有多个 实现时,通常用继承来协调他们。抽象类定义对该抽象的接口,而具体的子类则用不同的方式来实现。但是此方法有时候不太灵活。继承机制将抽...

    xiangzhihong

扫码关注云+社区

领取腾讯云代金券