zoukankan      html  css  js  c++  java
  • 超轻量级高性能ORM数据访问组件Deft,比dapper快20%以上

    超轻量级高性能ORM数据访问组件Deft,比dapper快20%以上

    Deft简介

    Deft是一个超轻量级高性能O/R mapping数据访问组件,简单易用,几分钟即可上手。
    原文地址:http://www.cnblogs.com/StrangeCity/p/5566471.html

    Deft包含如下且不限于此的优点:

    1、按照Transact-SQL的语法语义风格来设计,只要调用者熟悉基本的Transact-SQL语法即可瞬间无忧开码,大大降低了学习Deft的成本,甚至零成本。
    2、Deft表示性能方面真不是针对谁,包括纯手工代码。通过缓存+Emit反射IDataReader,极速获取List<T>。
    3、强大的查询功能,任意组装where条件,支持各种各样的运算符和括号优先级,支持给查询字段取别名。
    4、支持SQLServer、MySQL、Oracle、SQLite等多数据库类型,同时也支持一个业务系统里面存在多个数据库。
    5、支持事务、分页查询、排序等。
    6、支持like,in等sql操作符,支持avg,count,max,min,sum等sql函数。
    7、颜值高,支持Lambda 表达式,链式编程,任意组装sql,极度美观。
    8、支持手写sql, List<T> Select<T>(string sql)。
    9、各种映射能力,包括任意查询的结果映射,支持dynamic。
    10、实体类非常简单,手写即可,不需要借助工具,也没有特性标记或者继承BaseEntity等杂七杂八的东西。
    11、参数化赋值,防止sql注入。
    12、开放DbHelper,满足特定使用场景(比如考勤报表),可以直接执行成百上千行的复杂sql。
    13、对象化操作,编译时检查。使用Lambda 表达式做写入操作时,只会对表达式指定的字段做写入操作。
    14、调用代码极其简单,干净清爽,可读性强,方便维护。
    15、对外抛出OnDbExecute事件,调用方可自行处理日志埋点、sql监控等。
    16、开发效率快,基本无配置,无工具支持也可以开发(例如 NHibernate 配置起来就比较繁琐)。
    17、超轻量,Entity Framework 和 NHibernate 则臃肿不堪。
    18、......等您来发现

    不需要xxx入门系列,不需要xxx开发文档,不需要xxx使用教程,不需要繁琐的配置,不需要晦涩难懂的使用方式,不需要xxx。。。一切从简。
    因为Deft的设计使用初衷就是一个初学者花30秒钟配置数据库连接信息,然后花3分钟扫一眼和Transact-SQL极度相似的链式语法就可以做到对数据库的访问。

    编译后的Release版本只有60KB,dapper体积的一半左右

    为什么叫Deft?
     

    Deft 核心类介绍

    Deft共计有4个核心类
    Jugg      用于对外提供ORM核心方法的静态类
    JuggContext      用于对外提供ORM核心方法的实例类
    JuggDbHelper    用于数据库访问的帮助类
    JuggConfig    用于设置一些配置项的静态类

    Jugg一词来源于游戏中的剑圣,是一个敏捷且攻击属性都很强的战斗英雄

    Deft 3分钟即可上手使用

    实体类

    复制代码
    public class UserInfo
    {
        public Int32 Id { get; set; }
    
        public String Name { get; set; }
    
        public Byte? Age { get; set; }
    
        public Byte? Sex { get; set; }
    
        public String Email { get; set; }
    
        public String Address { get; set; }
    
        public String Remark { get; set; }
    
        public Object Test { get; set; } //无意义字段
    }
    复制代码

    .config文件中配置数据库连接信息

    硬编码也可以配置数据库连接信息,遵守约定大于配置

    JuggConfig.DefaultDbConCfg = new ConnectionStringSettings { ProviderName = "System.Data.SqlClient", ConnectionString = "server=.;database=Northwind;integrated security=SSPI" };

    强大灵活且易用的语法 

    复制代码
    //简单查询
    var list = Jugg.Select<UserInfo>().Query();
    
    //查询指定的几个字段
    list = Jugg.Select<UserInfo>(x => x.Name).Query();
    list = Jugg.Select<UserInfo>(x => new { x.Id, x.Name, x.Email }).Query();
    
    //查询的时候,给字段取别名
    list = Jugg.Select<UserInfo>(x => new { UserId = x.Id, UserName = x.Name, x.Email }).Query();
    
    //带简单where条件
    int idParameter = 23;
    list = Jugg.Select<UserInfo>().Where(x => x.Id != idParameter).Query();
    
    //强大的查询功能,任意组装where条件
    int[] aryId = { 1, 2, 3 };
    list = Jugg.Select<UserInfo>().
                Where(x =>
                        x.Id != null &&                          // where Id is not null
                        (x.Age > 18 || x.Email == null) &&       // and ( Age>18 or Email is null )
                        x.Id.ToString().Contains("8") &&         // and Id like '%8%'
                        aryId.Contains(x.Id) &&                  // and Id in (1,2,3)
                        x.Name.StartsWith("张") &&               // and Name like '张%'
                        x.Remark.EndsWith("test") &&             // and Remark like '%test'
                        x.Email.Contains("@qq.com") ||           // and Email like '%@qq.com%'
                        x.Address != null                        // or  Address is not null
                        ).
                Query();
    
    //排序
    list = Jugg.Select<UserInfo>().Where(x => x.Id > 0).OrderBy(x => x.Id).Query();
    list = Jugg.Select<UserInfo>().
                Where(x => x.Id > 0).
                OrderByDesc(x => x.Id).
                Query();
    
    //分页查询
    list = Jugg.Select<UserInfo>().
                Where(x => x.Id != null && (x.Age > 18 || x.Email == null)).
                GetPage().            //查询第1页,每页记录数读取JuggConfig.PageRecordCount配置的值
                Query();
    list = Jugg.Select<UserInfo>().
                GetPage(5, 80).       //查询第5页,每页80条记录
                Query();
    
    //查询某一个范围的记录
    list = Jugg.Select<UserInfo>().
                GetRange(337, 100).       //查询第337~437条记录
                Query();
    
    
    //手写sql查询,支持dynamic映射
    List<dynamic> listDynamic = Jugg.Select("select * from UserInfo where Id>99;");
    list = Jugg.Select<UserInfo>("select * from UserInfo where Id>99;");
    
    listDynamic = Jugg.GetPage("select * from UserInfo where Id>99;");
    list = Jugg.GetPage<UserInfo>("select * from UserInfo where Id>99;");
    
    listDynamic = Jugg.GetRange("select * from UserInfo where Id>99;");
    list = Jugg.GetRange<UserInfo>("select * from UserInfo where Id>99;");
    
    
    //单条记录查询
    var u = Jugg.Find<UserInfo>(x => x.Id == 0);
    u = Jugg.Single<UserInfo>(x => x.Id == 239);
    
    //根据条件判断记录是否存在
    bool b = Jugg.Exists<UserInfo>(x => x.Id == 105);
    
    //Max 函数返回一列中的最大值。null 值不包括在计算中。
    int uid = Jugg.Max<UserInfo>(x => x.Id).Query<int>();
    
    //Min 函数返回一列中的最小值。null 值不包括在计算中。
    uid = Jugg.Min<UserInfo>(x => x.Id).Where(x => x.Id > 1000).Query<int>();
    
    //Avg 函数返回数值列的平均值。null 值不包括在计算中。
    int age = Jugg.Avg<UserInfo>(x => x.Age).Query<int>();
    
    //Sum 函数返回数值列的总数(总额)。
    age = Jugg.Sum<UserInfo>(x => x.Age).Query<int>();
    
    //Count(*) 函数返回表中的记录数。
    int count = Jugg.Count<UserInfo>().Query<int>();
    
    //Count(column_name) 函数返回指定列的值的数目(null 不计入)。
    count = Jugg.Count<UserInfo>(x => x.Name).Query<int>();
    
    
    //增删改            
    int id = Jugg.Insert(new UserInfo { Name = "张三" });//根据传入的对象来新增
    id = Jugg.Insert<UserInfo>(x => new { x.Name, x.Age }, "李四", 18);//根据Lambda 表达式,只新增指定的字段
    
    
    int affectedRowsNum = Jugg.Delete(new UserInfo { Id = 668 });//根据传入对象的Id删除
    affectedRowsNum = Jugg.Delete<UserInfo>().Where(x => x.Id == 23 && x.Name != null).Execute();//根据where条件删除
    affectedRowsNum = Jugg.Delete<UserInfo>().Execute();//全表删除
    
    
    affectedRowsNum = Jugg.Update(new UserInfo { Id = 569, Name = "张三update" });//根据传入的对象来更新
    
    affectedRowsNum = Jugg.Update<UserInfo>(x => new { x.Name }, "张三").
                            Where(x => x.Id == 23).Execute();//根据Lambda 表达式,只更新指定的字段
    
    
    //通过JuggContext上下文来执行事务
    using (JuggContext context = new JuggContext())
    {
        try
        {
            context.BeginTransaction();
    
            id = context.Insert<UserInfo>(a => new { a.Name, a.Email, a.Age }, "张三", "123456@qq.com", 22);
    
            int r1 = context.Update<UserInfo>(x => new { x.Name }, "张三98261571").
                                Where(x => x.Id == id).
                                Execute();
    
            int r2 = context.Delete<UserInfo>().
                                Where(a => a.Id == id).
                                Execute();
    
            bool r3 = context.Exists<UserInfo>(x => x.Id == id);
    
            if (id > 0 && r1 == 1 && r2 == 1 && !r3)
            {
                context.Commit();
            }
            else
            {
                context.Rollback();
            }
        }
        catch
        {
            context.Rollback();
        }
    }
    复制代码

    其他可选的配置参数

    复制代码
    JuggConfig.Debug = true;//开启调试,默认是未开启
    
    //添加类型无效值,用于过滤不必要的字段
    JuggConfig.PropertyTypeInvalidValue.Add(typeof(byte), default(byte));
    JuggConfig.PropertyTypeInvalidValue.Add(typeof(int), default(int));//public int Age { get; set; },如果属性值为0,则会被Deft自动忽略
    
    JuggConfig.DefaultPrimaryKeyColumnName = "Id";//设置主键名称,默认是 Id
    
    JuggConfig.DeftDbConStrKeyName = "DeftDbCon";//配置.config文件中connectionStrings的key,Deft会自动去加载,默认是DeftDbCon
    
    //硬编码配置数据库连接对象
    JuggConfig.DefaultDbConCfg = new ConnectionStringSettings { ProviderName = "System.Data.SqlClient", ConnectionString = "server=.;database=Northwind;integrated security=SSPI" };
    
    JuggConfig.PageRecordCount = 50;//设置分页的每页记录数,默认是50
    
    JuggDbHelper.OnDbExecute += OnDbExecute;//数据库执行事件,必须先通过设置JuggConfig.Debug开启调试模式才会起效果,默认是订阅的
    
    static void OnDbExecute(DbConnection con, string sql, DbParameterCollection dbParameters)
    {
        //TODO sql日志埋点
        string dbParamsStr = null;
        foreach (DbParameter item in dbParameters)
        {
            dbParamsStr += string.Format("{0}:{1}  ", item.ParameterName, item.Value);
        }
        Console.WriteLine(string.Format("{0}{1}{2}{1}", sql, Environment.NewLine, dbParamsStr));
    }
    复制代码

      

    性能测试


    刚刚完工,还有很多不足之处,希望大家多给些意见和需求,cnblogs社区的热度是我强劲的动力。 
    Deft确实不够完美,没有办法去满足上帝视角,如果可以,希望点 “反对” 的同学能够在评论下方给出您的建议和点评。

    cnblogs作为国内最大的.NET技术社区,我公开发表技术文,本着严谨治学,虚心接受的态度,愿意为自己的言论负责。
    再就是dapper的性能不是不可超越,国外的月亮真的天天比国内圆?
    如果大家热度高,下一篇,我会专门讲解Deft背后的技术揭秘。

    多表语法的设计和解析早就已经完成了,另外多表mapping还在优化中,暂时没有开放。

    Demo代码下载

  • 相关阅读:
    浅拷贝在项目中的应用
    MVC3中使用AuthorizeAttribute特性来完成登陆权限的验证
    一个面向对象的JS例子,很好的支持了开闭原则(不要重复你昨天的代码)
    c++学习笔记5
    JS跨域访问操作iframe
    Select函数
    MacOS10.8.3+Xcode4.6+IOS6.1 编译FFmpeg,简单使用
    eclipse部署,在tomcat中找不到eclipse发布的项目。eclipse更改项目发布路径
    初识Volley(二)
    MySQL 5.0 迁移到 MariaDB 10.0.2 存储过程无法迁移
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5709768.html
Copyright © 2011-2022 走看看