为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
深度学习

为什么开发(背景)

  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项目作者开源

原文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消