ORM之一:適合我的ORM


  一、常見開源ORM框架

 

  比喻:Kerosene ORM,DbLinq,Dapper,DynamicQuery,elinq,glinq,NPoco,Relinq,EF,ServiceStack.OrmLite,IQToolkit,對於這些框架,在單表查詢這塊支持的還蠻可以,但是對於多表查詢的那種語法,我真有點接受不了,總感覺怪怪的,直觀感覺就是沒有了linq語法的那種美感,請忽視我的挑剔與自不量力,純屬個人喜好。

 

  例如:

 

var cmd = link
   .From( x => x.Employees.As( x.Emp ) ) .Join( x => x.Countries.As( x.Ctry ).On( x.Emp.CountryId == x.Ctry.Id ) ) .Select( x => x.Emp.Id, x => x.Emp.FirstName, x => x.LastName ) .Select( x => x.Ctry.Id, x => x.Ctry.Name ) .OrderBy( x => x.Emp.Id );

 

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

 

var joinQuery = new JoinSqlBuilder<User, User> ().
                LeftJoin<User, Address> (x => x.Id, x => x.UserId).ToSql ();

 

 var testQuery = from c in db.Customers
                            from o in c.Orders from d in o.Details where o != exclude select d; var test = testQuery.ToList();

 

var query = from c in db.Customers
                        where c.CustomerID == "ALFKI" join o in db.Orders on new {a = c.CustomerID, b = c.CustomerID} equals new {a = o.CustomerID, b = o.CustomerID} select new {c, o};

 

等等。其次就是代碼量相當龐大,閱讀起來費力,雖然都是從接口、抽象類開始閱讀,而且調試起來去理解它的代碼需要耗費大量時間,且相關文檔有些不完整。再次陷入了困境,前前后后也花了一些時間,於是靜下心來想想,為何我不重新梳理下自己的計划了,原本是想在前人的基礎上去修改修改就變成自己的了,但是核心代碼還是別人的,自己沒有掌握關鍵技術。看來這條路走不通了,只能靠自己了。   

 

  二、ORM所需具備的條件

  在日常開發中,如果是做業務邏輯開發一定會離不開單表增刪改查、多表關聯查詢、存儲過程、分頁、聚合函數使用等。這里插播一段,因為我主要做后端開發以及框架搭建,平日最討厭某某說,后台不就是增刪改查嗎?只要一聽到類似的話語,我心中立即會有10萬頭草泥馬向他奔去,鄙夷感頓生。但是馬上會說,你怎么知道就只有增刪改查了?哈哈。有點扯遠了。不管是業務邏輯離不開這些,就一些框架組件也會將一些數據持久化,它們也離不開與數據庫打交道。那么我覺得這個ORM必須具備如下條件:

  A、支持CRUD標准接口;

  B、支持多表聯合查詢接口,並且使用linq語法,但是一定不使用linq的那個join方式;

  C、支持聚合函數、支持分組以及hanving、支持存儲過程調用、支持分頁,支持sql語句,支持事務;

  D、支持部分常用C# 函數調用;

  E、支持與元數據進行映射的工具;

  F、能擴展oracle,mysql等主流數據庫;

  如果能滿足上述6個大條件,那么這個輪子基本上就滿足日常開發中80%左右的場景了,那么快速開發也就不在話下了。

  

  三、適合我的ORM操作示例

  有了上面的基礎,結合一下目前主流的ORM框架,那么就可以想象下ORM的部分使用示例了。

  A、單表增刪改查

  Insert:

Db<T>.Insert(實體對象);

  Delete:

Db<T>.Delete(w => w.條件字段== 4);

  Update:

Db<T>.Update(up => new 實體對象{需要修改字段= "xxxxxx" }, wh => wh.條件字段== 4);

  Select:

Db<T>.Single(w => w.條件字段.Contains("@")); //單條記錄
Db<T>.Select(w => w.條件字段.Contains("@")); //多條記錄

  B、多表聯合查詢

  join:

var results = (from u in Db<T>.查詢對象a
                  join ur in Db<T>.查詢對象b on new
                  {
                      u = u.條件字段1,
                      a = u.條件字段2
                  } equals
                    new
                    {
                        u = ur.條件字段1,
                        a = ur.條件字段2
                    }
                  join r in Db<T>.查詢對象c on ur.條件字段3 equals r.條件字段3
                 where u.條件字段4 == 1
                  orderby u.條件字段5
                 select new object  //可以匿名 select new
                 {
                    v= u.字段,
                    vv= u.字段,
                    vvv= u.字段,
                    vvvv= r.字段
                  }).設置表關聯類型(類型Inner, 類型.left);

  分頁:

results.Page(1,1);

  C、存儲過程

var dbParameters = new DbParameterCollection
{
  new DbParameter{DbType = DbType.Int32,Name = 輸入參數名稱,Value = 1,Direction = ParameterDirection.Input},
new DbParameter{DbType = DbType.Int32,Name = 輸出參數名稱,Direction = ParameterDirection.Output }
};

var affectCount = Db.執行存儲過程(存儲過程名稱, 存儲過程參數); //這里是返回影響行數,還可以擴展返回ilist<T>集合,dataset對象

var returnc = dbParameters[output參數名稱].Value;

  D、執行sql語句

var ds = Db.執行查詢("select * from demoTable"); //還可以擴展返回ilist<T>集合,影響行數等
foreach (DataRow row in ds.Tables[0].Rows) { Console.WriteLine(row[0]); }

  E、事務

using (var 數據庫對象提供者實例= Db.默認實例)
{
    try
    {
      Begin(); //開始事務

       //to do...

      Commit(); //提交事務
    }
    catch (Exception)
    {
      Rollback(); //回滾事務
    }
}

  F、多表聯合查詢分組

var resultList = (from a in Db<T>.查詢對象1
                            join b in Db<T>.查詢對象1 on a.條件字段1 equals b.條件字段2
                  group new {對象a, 對象b} by new {對象a.字段}
                    into g
                  where g.Sum(m=>m.對象b.字段)>200
                  select new
                  {
                    userId= g.Key.對象a.字段,
   TotalScore
= g.Max(b => b.對象b.字段) }).ToList();

  G、其他就不一一列舉了,具體詳見后續博文。

     


免責聲明!

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



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