SqlSugar轻量ORM
蓝灯软件数据股份有限公司项目,代码开源。
SqlSugar是一款轻量级的MSSQL ORM ,除了具有媲美ADO的性能外还具有和EF相似简单易用的语法。
学习列表
3、使用SqlSugar实现Join 待更新
4、使用SqlSugar实现分页+分组+多列排序 待更新
5、节点故障如何进行主从调换
一、介简
优点:
1、优越的性能,查询使用 reflection.emit 创建IL语言+委托绑定 然后对该对象进行 cache ,datareader直接赋值给cache对象,高性能拉姆达解析,总体性能媲美 ADO.NET ,查询速度稍慢于datareader但稍快于datatable
2、大量语法糖,拉姆达表达示筛选,新颖的多表查询 ,方便的分页等
3、支持NOLOCK查询,提高性能
4、支持事务
5、内置实体类生成函数,无需使用第三方代码生成器
6、简单好用、例子齐全有问必答。
缺点:
目前只支持MSSQL,以后会全面发展
组成:
sqlSugar是由sqlSugarClientr提供统一调用模式 ,sqlSugarClientr是由5个部分组成
1、自身函数
2、实体生成
3、单表查询
4、多表查询
5、基类函数
如图:
二、使用教程
查询
1、单表或者单视图查询:
通过调用 db.Queryable() 的相关扩展函数 轻松搞定单表查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
using (SqlSugarClient db = new SqlSugarClient(connStr)) //开启数据库连接 { //查询所有 var student = db.Queryable<Student>().ToList(); //查询单条 var single = db.Queryable<Student>().Single(c => c.id == 1); //取10-20条 var page1 = db.Queryable<Student>().Where(c => c.id > 10).OrderBy( "id" ).Skip(10).Take(20).ToList(); //上一句的简化写法,同样取10-20条 var page2 = db.Queryable<Student>().Where(c => c.id > 10).OrderBy( "id" ).ToPageList(2, 10); //查询条数 var count = db.Queryable<Student>().Where(c => c.id > 10).Count(); //从第2条开始以后取所有 var skip = db.Queryable<Student>().Where(c => c.id > 10).OrderBy( "id" ).Skip(2).ToList(); //取前2条 var take = db.Queryable<Student>().Where(c => c.id > 10).OrderBy( "id" ).Take(2).ToList(); // Not like var notLike = db.Queryable<Student>().Where(c => !c.name.Contains( "a" .ToString())).ToList(); // 可以在拉姆达使用 ToString和 Convert,比EF出色的地方 var convert1 = db.Queryable<Student>().Where(c => c.name == "a" .ToString()).ToList(); var convert2 = db.Queryable<Student>().Where(c => c.id == Convert.ToInt32( "1" )).ToList(); // var convert3 = db.Queryable<Student>().Where(c => DateTime.Now > Convert.ToDateTime( "2015-1-1" )).ToList(); var convert4 = db.Queryable<Student>().Where(c => DateTime.Now > DateTime.Now).ToList(); //支持字符串Where 让你解决,更复杂的查询 var student12 = db.Queryable<Student>().Where(c => 1 == 1).Where( "id>@id" , new {id=1}).ToList(); } |
1
2
3
|
//存在记录反回true,则否返回false bool isAny100 = db.Queryable<Student>().Any(c => c.id == 100); bool isAny1 = db.Queryable<Student>().Any(c => c.id == 1); |
2、单表高级查询
根据条件查询并分页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/// <summary> /// 根据条件查询并且分页 /// </summary> /// <param name="name"></param> /// <param name="sex"></param> /// <returns></returns> public static List<Student> GetStudent( string name, string sex, int pageIndex, int pageSize, string orderFileds, out int pageCount) { using (SqlSugarClient db = SugarDao.GetInstance()) { var qable = db.Queryable<Student>(); if (! string .IsNullOrEmpty(name)) { qable = qable.Where(it => it.name.Contains(name)); } if (! string .IsNullOrEmpty(sex)) { qable = qable.Where(it => it.sex == sex); } if (! string .IsNullOrEmpty(orderFileds)) //无需担心注入 { qable = qable.OrderBy(orderFileds); } pageCount = qable.Count(); return qable.ToPageList(pageIndex, pageSize); } } |
新容器转换
1
2
3
4
5
6
7
|
public List<classNew> GetSelectList( int id) { using (SugarDao db = new SugarDao()) { return db.Queryable<Student>().Where(c=>c.id<10).Select(c => new classNew { newid = c.id, newname = c.name,xx_name=c.name }).ToList(); //不支持匿名类转换,也不建议使用 } } |
分组查询
1
2
3
4
5
6
7
|
public List<SexTotal> GetSexTotal() { using (SugarDao db = new SugarDao()) { return db.Queryable<Student>().Where(c => c.id < 20).GroupBy( "sex" ).Select<Student, SexTotal>( "Sex,Count=count(*)" ).ToList(); } } |
1
|
SELECT Sex, Count = count (*) FROM Student WHERE 1=1 AND (id < 20) GROUP BY Sex --生成结果 |
3、多表查询:
说到多表查询在众多ORM中无论是性能还是功能上都不满意,或者说还不如用SQL,下面是我的创意,放弃了强类型写法,让代码更接近SQL语句编写,让SQL完全可控,也解决了OMR多表的性能问题。
还有ORDERBY、GROUPBY和APPLY等,例子中就不介绍了。
拿EF来比较一下:
EF查询:
1
2
3
4
5
6
7
8
9
10
11
|
var reval = ( from s in db.Student join sc in db.School on s.sch_id equals sc.id join sb in db.Subject on s.id equals sb.sid into ssb from sb2 in ssb.DefaultIfEmpty() select new { s.id, s.name, s.sch_id, s.sex }).Where(c=>c.id>1).Where(c=>c.id>2).OrderBy(c=>c.id).ThenByDescending(c=>c.name).Skip(10).Take(10).ToList(); |
SqlSugar查询:
1
2
3
4
|
db.Sqlable().Form<Student>( "s" ) .Join<School> ( "sc" , "sc.id" , "s.sch_id" , JoinType.INNER) .Join<subject>( "sb" , "sb.sid" , "s.id" , JoinType.LEFT).Where( "s.id>@id1" ).Where( "s.id>@id2" ) .SelectToPageList<Models.Student>( "s.*" , "s.id asc,s.name desc" , 2, 10, new { id1=1,id2=2 }); |
更多的SqlSugar查询:
1
2
3
4
5
6
7
8
9
10
11
|
//表名是字符串写法 List<School> dataList = db.Sqlable() .Form( "school" , "s" ) .Join( "student" , "st" , "st.id" , "s.id" , JoinType.INNER) .Join( "student" , "st2" , "st2.id" , "st.id" , JoinType.LEFT).Where( "s.id>100 and s.id<@id" ).SelectToList<School>( "st.*" , new { id = 1 }); //多表分页 List<School> dataPageList = db.Sqlable() .Form<school>( "s" ) .Join<student>( "st" , "st.id" , "s.id" , JoinType.INNER) .Join<student>( "st2" , "st2.id" , "st.id" , JoinType.LEFT).Where( "s.id>100 and s.id<100" ).SelectToPageList<School>( "st.*" , "s.id" , 1, 10); |
子查询加动态拼接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public List<Student> GetStudent( int id, string name) { int pageCount = 0; using ( var db = SugarDao.GetInstance()) { //Form("Student","s")语法优化成 Form<Student>("s") var sable = db.Sqlable().Form<Student>( "s" ).Join<School>( "l" , "s.sch_id" , "l.id" , JoinType.INNER); if (! string .IsNullOrEmpty(name)) { sable = sable.Where( "s.name=@name" ); } if (! string .IsNullOrEmpty(name)) { sable = sable.Where( "s.id=@id or s.id=100" ); } if (id > 0) { sable = sable.Where( "l.id in (select top 10 id from school)" ); //where加子查询 } //参数 var pars = new { id = id, name = name }; pageCount = sable.Count(pars); return sable.SelectToList<Student>( "s.*" , pars); } } |
4、 使用SQL或者存储过程查询:
为了兼容上面满足不了的情况所以也写了这么个函数以便应急之需
1
2
3
4
5
6
7
8
9
10
|
var School = db.SqlQuery<School>( "select * from School" ); //获取id var id = db.SqlQuery< int >( "select top 1 id from School" ).Single(); //存储过程 //var spResult = db.SqlQuery<school>("exec sp_school @p1,@p2", new { p1=1,p2=2 }); //无返回值 db.ExecuteCommand(sql); |
添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
using (SqlSugarClient db = new SqlSugarClient(connStr)) //开启数据库连接 { School s = new School() { name = "蓝翔" }; //插入单条 var id2 = Convert.ToInt32(db.Insert(s)); //插入多条 List<School> sList = new List<School>(); sList.Add(s); var ids = db.InsertRange(sList); } |
修改
1
2
3
4
|
//指定列更新 db.Update<School>( new { name = "蓝翔2" }, it => it.id == id); //整个实体更新,注意主键必需为实体类的第一个属性 db.Update<School>( new School { id = id, name = "蓝翔2" }, it => it.id == id); |
删除
1
2
3
4
5
6
7
|
db.Delete<School>(id); //注意主键必需为实体类的第一个属性 db.Delete<School>(it => it.id > 100); db.Delete<School>( new string [] { "100" , "101" , "102" }); db.FalseDelete<school>( "is_del" , 100); //假删除 //等同于 update school set is_del=0 where id in(100)<br> db.FalseDelete<school>( "is_del" , it=>it.id==100); |
更多底层函数
1
2
3
4
5
6
7
8
9
10
|
db.ExecuteCommand(sql); db.GetDataTable(sql); db.GetList<Student>(sql); db.GetSingle<Student>(sql + " where id=1" ); using (SqlDataReader read = db.GetReader(sql)) { } //事务中一定要释放DataReader db.GetScalar(sql); db.GetString(sql); db.GetInt(sql); |
实体生成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
using (SqlSugarClient db = new SqlSugarClient(connStr)) //开启数据库连接 { //根据当前数据库生成所有表的实体类文件 (参数:SqlSugarClient ,文件目录,命名空间) db.ClassGenerating.CreateClassFiles(db,Server.MapPath( "~/Models" ), "Models" ); //根据表名生成实体类文件 db.ClassGenerating.CreateClassFilesByTableNames(db, Server.MapPath( "~/Models" ), "Models" , "student" , "school" ); //根据表名生成class字符串 var str = db.ClassGenerating.TableNameToClass(db, "Student" ); //根据SQL语句生成class字符串 var str2 = db.ClassGenerating.SqlToClass(db, "select top 1 * from Student" , "student" ); } |
事务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
using (SqlSugarClient db = new SqlSugarClient(connStr)) //开启数据库连接 { try { //开启事务,可以不使用事务,也可以使用多个事务 db.BeginTran(); //sq1 //sql2 //sql3 } catch (Exception ex){ //回滚事务 db.RollbackTran(); throw ex; } } //关闭数据库连接 |
无锁查询
当IsNoLock设为True时,查询生成的SQL语句表名的后面都会带有With(Nolock)
1
2
3
4
5
6
7
8
9
10
11
|
using (SqlSugarClient db = new SqlSugarClient(connStr)) //开启数据库连接 { db.IsNoLock = true ; //sql xxx with(nolock) db.IsNoLock = false ; //sql xxx //sql xxx db.IsNoLock = true ; //sql xxx with(nolock) } //关闭数据库连接 |
支持多库切换的写法
定义一个sugarDao类来扩展SqlSugar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/// <summary> /// 扩展SqlSugarClient /// </summary> public class SugarDao { //禁止实例化 private SugarDao() { } public static SqlSugarClient GetInstance() { string connection = "Server=.;uid=sa;pwd=sasa;database=SqlSugarTest" ; //这里可以动态根据cookies或session实现多库切换 return new SqlSugarClient( connection ); } } |
使用无需传入connectionString
1
2
3
4
5
6
7
|
public School GetSingleSchool( int id) { using (SqlSugarClient db = SugarDao.GetInstance()) { return db.Queryable<School>().Single(c => c.id == id); } } |
三、性能测试:
10000次
1000次
10000次
.net4.52+EF 6.0+SQL12 以洗耻辱
.NET Framework 4.52+ sql12 +EF6.0 ,EF性能明显上去了,就让它当个冠军吧,我也不去测试了,微软的东西升级后性能无需质疑,在多表查询和添删改方面综合下来也基本平手。
SqlSugar追求的是轻量、上手快、简单易用对SQL的可控性,也希望你能喜欢或者提出您宝贵意见。
V1.0源码下载地址:
http://pan.baidu.com/s/1bnmAXjh
V1.2源码下载地址:
http://pan.baidu.com/s/1jGENyQi
更改内容:
contains查询BUG,SQL拼接BUG
V1.3源码下载地址:
http://pan.baidu.com/s/1kTrRbmR
更改内容:
添加 queryable/sqlable to dataTable
CACHE BUG修复
支持 int?类型这类 nullable类型
此版本稳定,多家公司正在使用
有一点需要声名如果主键不是identity需要写成 insert(obj,false)这不是BUG
主键位置在类中可以任意放无需放第一个
V1.5源码下载地址:
http://pan.baidu.com/s/1pJ8F0dt
更改内容:
1、代码结构优化
2、删除语法需要注意
以前删除
db.Delete<School>(new string[] { "100", "101", "102" });
需要改成下面这种写法
db.Delete<School,string>(new string[] { "100", "101", "102" });
3、添加批量更新
db.Update<School, string>(new { name = "蓝翔2" },new string []{"1","2"});