继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

LambdaToSql(轻量级ORM) 入门篇 开源项目

30秒到达战场
关注TA
已关注
手记 419
粉丝 95
获赞 569

为什么开发(背景)

  1. 最开始使用的是 sqlDbHelper,有微软的,有自己写的。

  2. 后来开始使用比较成熟的框架开发,使用过一段时间的Hibernate,后期主要使用 Entity FrameWork。

  3. 发现表越多 业务越复杂后,越不好控制项目,所以慢慢的自己根据业务写了一个小工具,也就是本文说的 LambdaToSql。

  4. 最开始的功能 主要是准备替代DbHelper的,慢慢的把映射关系加上了,再后来重构了几次,就慢慢的代替了EF的功能。

  5. 现在有几个成熟的项目在使用,软件也会一直维护下去,现在基本都是核心功能,暂时没往大而全去做。

ORM介绍

  1. 链式查询、链式更新、链式删除、链式插入、复杂模型的查询、ADO.NET。

  2. 支持数据库:现在只支持 MS Sql Server,其他数据库暂时未做支持处理,里面预留了对其它数据库支持的接口,但未实现代码逻辑。

  3. 数据库预留接口:Oracle、Mysql、Access。

  4. 功能: 基本CURD(添加,修改,读取,删除)功能,批量修改,DbFirst,表缓存。

  5. 全部使用Lambda语法,开发简洁,代码干净,后期好维护。

  6. 有点2:性能高,基本接近于原生ADO,语法简单,功能强大,持续更新维护。

  7. 其实LambdaToSql不能算是一个ORM,主要功能其实还应该算是Dapper替代产品,主要是把映射对象通过Lambda形式转换成sql语句,通过Ado做 CURD操作。

  8. 缺点1:不支持多表查询,Join性能还是比较低,但后期还是会支持join查询。

  9. 缺点2:暂时不支持外部自定义函数和继承覆盖重写,后期慢慢也会开放出来。

  10. 如果有想自定义的,可以直接使用源码改动哦。

 

性能测试

  1. 测试环境:   硬盘:三星 SSD 850 EVO;     CPU:i7-7700K

  2. 添加100w条数据 耗时大概250s内

  3. 查询100w条数据并生成实体.Tolist(),大概3s

  4. 100w数据,每页50条,取中间数据,大概100ms内

  5. 插入/更新/查询 单条数据 大概20ms内

  6. 删除 单条大概 20ms内

 

开源地址

  1. 码云gitee: https://gitee.com/wangshuyu/LambdaToSql

  2. Demo示例:https://gitee.com/wangshuyu/LambdaToSql_Demo

 

如何安装

  1. 源码方式:可以直接在gitee下载源代码,在项目中直接使用

  2. 通过Nuget下载引用: 打开Nuget  搜索:LambdaToSql 就可以了

  3. Nuget命令方式:  Install-Package LambdaToSql

 

Config配置,链接数据库 

  <connectionStrings>
    <add name="ConnectionString" connectionString="Server=.;Database=LambdaToSql;User ID=sa;Password=abc@123;" providerName="System.Data.SqlClient" />
  </connectionStrings>

 

初始化LambdaToSql 对象

//默认方式LambdaToSql.SqlClient DB = new LambdaToSql.SqlClient();
//自定义链接字符串名称var DB = new LambdaToSql.SqlClient(new LambdaToSql.EntityModel.DbContext()
            {
               ConnectionStringName = "ConnectionString1",
               SqlType = LambdaToSql.EntityModel.SqlType.MsSqlServer
            });

  

初次使用,如何生成实体类:DbFirst

复制代码

//生成实体保存路径var saveFolder = "d:\\class\\";//生成全部实体DB.DbFirst.Create(saveFolder);//生成指定表实体对象DB.DbFirst.CreateByTable(saveFolder, new List<string>() { "Table_ID", "Table_Guid" });

复制代码

 

查询

复制代码

/// <summary>/// 查询/// </summary>public void Query()
{    //查询全部
    var list = DB.QueryTable<EntityModel.Table_ID>().ToList();    //Find主键查找,支持Guid 和int 自增主键
    var entity = DB.QueryTable<EntityModel.Table_ID>().Find(200);    //In查询
    var arr = new int?[] { 100, 101, 102, 103 }.ToList();    var list1 = DB.QueryTable<EntityModel.Table_ID>(ex => arr.Contains(ex.ID)).ToList();    //Not In 查询 
    var list2 = DB.QueryTable<EntityModel.Table_ID>(ex => ex.ID.ExNotIn(arr)).ToList();//有问题
    var list2_1 = DB.QueryTable<EntityModel.Table_ID>(ex => arr.NotContains(ex.ID)).ToList();//有问题    // Like  查询
    var list3 = DB.QueryTable<EntityModel.Table_ID>().Where(ex => ex.LoginName.Contains("15")).ToList();//(LoginName like '%15%')
    var list4 = DB.QueryTable<EntityModel.Table_ID>().Where(ex => ex.LoginName.NotContains("15")).ToList();//(LoginName not like '%15%') //有问题
    var list5 = DB.QueryTable<EntityModel.Table_ID>().Where(ex => ex.LoginName.StartsWith("15")).ToList();//(LoginName like '15%')
    var list6 = DB.QueryTable<EntityModel.Table_ID>().Where(ex => ex.LoginName.EndsWith("15")).ToList();//(LoginName like '%15')    //排序
    var list7 = DB.QueryTable<EntityModel.Table_ID>().OrderBy(ex => ex.CreateTime).OrderByDescending(ex => ex.LoginName).ToList();    //分组
    var list8 = DB.QueryTable<EntityModel.Table_ID>().GroupBy(ex => new { ex.LoginName, ex.UserName }).ToList();    //只取特定字段
    var list9 = DB.QueryTable<EntityModel.Table_ID>().Select(ex => new { ex.LoginName, ex.UserName }).ToList();    //top N
    var list10 = DB.QueryTable<EntityModel.Table_ID>().Take(10).ToList();    //第几页
    var list11 = DB.QueryTable<EntityModel.Table_ID>().Skip(2).Take(10).ToList();    //取第一条数据
    var list12 = DB.QueryTable<EntityModel.Table_ID>().First();    var list13 = DB.QueryTable<EntityModel.Table_ID>().FirstOrDefault();    //分页  2005,2008使用row_number分页,2012以上使用offset分页形式
    int total = 0;    var list14 = DB.QueryTable<EntityModel.Table_ID>().Skip(15).Take(30).ToPageList(ref total);    //分组 select 比原始去重性能要高一些
    DB.QueryTable<EntityModel.Table_ID>().GroupBy(ex => new { ex.UserName, ex.LoginName })
                                            .Select(ex => new { ex.UserName, ex.LoginName })
                                            .ToList();    //判断满足条件的数据是否存在
    var flag = DB.QueryTable<EntityModel.Table_ID>().Any();    //判断满足条件的数据是否存在
    var flag1 = DB.QueryTable<EntityModel.Table_ID>(ex => ex.ID == 2000).Any();
}

复制代码

 

函数处理

复制代码

/// <summary>/// 函数处理/// </summary>private void Fun()
{    //求和
    var num1 = DB.QueryTable<EntityModel.Table_ID>().Sum(ex => ex.IsDelete);    //最小值
    var num2 = DB.QueryTable<EntityModel.Table_ID>().Min(ex => ex.IsDelete);    //最大值
    var num3 = DB.QueryTable<EntityModel.Table_ID>().Max(ex => ex.IsDelete);    //平均值
    var num4 = DB.QueryTable<EntityModel.Table_ID>().Avg(ex => ex.IsDelete);    //总数
    var num5 = DB.QueryTable<EntityModel.Table_ID>().Count();
}

复制代码

 

添加

复制代码

/// <summary>/// 添加数据/// </summary>public void Inser()
{    //添加单个实体对象
    var entity = new EntityModel.Table_ID()
    {
        LoginName = "登录用户:",
        UserName = "用户名:",
        PassWord = "密码-",
        Gender = "男",
        IsDelete = 0,
        Mobile = "15804066511",
        Remark = "备注",
        Address = "地址:",
        CreateTime = DateTime.Now
    };    var ret = DB.InsertTble(entity).ExecuteNonQuery();//返回主键值    //只添加某几列
    var i = DB.InsertTble(entity).InsertColumns(ex => new { ex.LoginName, ex.UserName, ex.Remark }).ExecuteNonQuery();    //忽略某些列
    var i1 = DB.InsertTble(entity).IgnoreColumns(ex => new { ex.Mobile, ex.PassWord }).ExecuteNonQuery();
}

复制代码

 

修改

  1. NULL列不做更新处理

  2. 暂时只支持uniqueidentifier和int自增类型单主键

复制代码

/// <summary>/// 更新数据/// </summary>public void Update()
{    //更新单个实体对象
    var entity = DB.QueryTable<EntityModel.Table_ID>(ex => ex.ID == 200).FirstOrDefault();
    entity.PassWord = "12345";
    entity.LoginName = "LambdaToSql";
    entity.UserName = "LambdaToSql1";    var i = DB.UpdateTble(entity).ExecuteNonQuery();    //更新特定字段,不指定不更新
    var i1 = DB.UpdateTble(entity).UpdateColumns(ex => new { ex.PassWord }).ExecuteNonQuery();    //忽略特定字段,其他字段都更新
    var i2 = DB.UpdateTble(entity).IgnoreColumns(ex => new { ex.UserName, ex.PassWord }).ExecuteNonQuery();    //条件更新 不需要取出实体对象 直接数据库更新             
    var i3 = DB.UpdateTble(new EntityModel.Table_ID() { PassWord = "123456", LoginName = "12" }).Where(ex => ex.ID == 101).ExecuteNonQuery(true);
}

复制代码

 

删除

复制代码

/// <summary>/// 删除/// </summary>public void Delete()
{    //删除单个实体,通过主键删除 
    var entity = DB.QueryTable<EntityModel.Table_ID>(ex => ex.ID == 200).FirstOrDefault();    var i = DB.DeleteTble<EntityModel.Table_ID>(entity).ExecuteNonQuery();    //条件删除 支持查询里面的所有条件写法
    var i1 = DB.DeleteTble<EntityModel.Table_ID>(ex => ex.ID == 201).ExecuteNonQuery();
}

复制代码

 

事务

事务使用注意:

  1. 事务只能在同一个SqlClient对象有效;事务只能在同一个SqlClient对象有效;事务只能在同一个SqlClient对象有效;重要的事说三遍

  2. 跨SqlClient对象请用分布式事务(暂时内置不支持,后续版本会支持分布式事务) 

复制代码

/// <summary>/// 事务/// </summary>public void Tran()
{    var sqlClient = new LambdaToSql.SqlClient();    try
    {
        sqlClient.BeginTran();//开启事务        //添加单个实体对象
        var entity = new EntityModel.Table_ID()
        {
            LoginName = "登录用户:",
            UserName = "用户名:",
            PassWord = "密码-",
            IsDelete = 0,
            CreateTime = DateTime.Now
        };        var entity1 = new EntityModel.Table_ID()
        {
            LoginName = "登录用户:",
            UserName = "在破败中崛起,在寂灭中复苏。沧海成尘,雷电枯竭,那一缕幽雾又一次临近大地,世间的枷锁被打开了,一个全新的世界就此揭开神秘的一角:",
            PassWord = "密码-",
            IsDelete = 0,
            CreateTime = DateTime.Now
        };        var entity2 = new EntityModel.Table_ID()
        {
            LoginName = "登录用户:",
            UserName = "用户名:",
            PassWord = "密码-",
            IsDelete = 0,
            CreateTime = DateTime.Now
        };


        sqlClient.InsertTble(entity).ExecuteNonQuery();
        sqlClient.InsertTble(entity1).ExecuteNonQuery();//错误 UserName太长=>回滚        sqlClient.InsertTble(entity2).ExecuteNonQuery();

        sqlClient.CommitTran();//提交事务    }    catch (Exception ex)
    {
        sqlClient.RollbackTran();//回滚事务    }
}

复制代码

 

ADO

复制代码

/// <summary>/// Ado/// </summary>public void Ado()
{    var sql = "select top(10) * from table_id";    var sdr = DB.Ado.ExecuteReader(sql);    var list = new List<string>();    while (sdr.Read())
    {
        list.Add(sdr[0].ToString());
    }
    sdr.Close();    var Dt = DB.Ado.ExecuteTable(sql);    var ls1 = DB.Ado.ExecuteScalar(sql);    var ls = DB.Ado.ExecuteScalars(sql);    var i = DB.Ado.ExecuteNonQuery("update top (10) table_id set imgurl = 'img1'");
}

复制代码

 

后续计划

  1. 继续维护代码和升级新功能

  2. 把类库UML图发布出来

  3. 把类接口和实现文档 整理好 发布出来

  4. 会在开源一个关于WebApi的整体框架结构

  5. 最近另一个开源项目: https://gitee.com/wangshuyu/CommonLib  这是个通用类库项目,把平时常用的整理了下,自己也一直在使用此类库

 

结尾

  1. 希望大家多多提bug

  2. 希望大家多多提意见

  3. 最后,感谢SqlSugar项目作者开源

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP