SqlSugar輕量ORM


 

藍燈軟件數據股份有限公司項目,代碼開源。

 

SqlSugar是一款輕量級的MSSQL ORM ,除了具有媲美ADO的性能外還具有和EF相似簡單易用的語法。

 

學習列表

  0、功能更新

 1、SqlSugar基礎應用

 2、使用SqlSugar處理大數據

 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"});


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM