本文介紹如何使用 Rafy 框架中的 Sql Tree 查詢:html
除了開發者經常使用的 Linq 查詢,Rafy 框架還提供了 Sql 語法樹的方式來進行查詢。git
這種查詢方式下,開發者不須要直接編寫真正的 Sql 語句,而是轉而使用一套中間 Sql 語法樹對象。這隔離了與具體數據庫的耦合,使得開發者編寫的查詢能夠跨越多種不一樣的數據庫運行,甚至能夠在非關係型數據庫中運行。同時,框架還結合託管屬性,提供了方便開發者使用的 API,並儘可能保持與傳統 Sql 相近的語法,使得開發者能夠快速理解並編寫。github
本文包含如下章節:數據庫
快速示例框架
SqlTree 查詢是直接以一種相似於 Sql 語法的格式,並結合實體託管屬性 IManagedProperty 來進行查詢的查詢模式。以下:性能
[RepositoryQuery] public virtual ChapterList GetBy(string name, PagingInfo pi) { var f = QueryFactory.Instance; var t = f.Table<Chapter>(); var q = f.Query( selection: f.SelectAll(),//查詢全部列 from: t,//要查詢的實體的表 where: t.Column(Chapter.NameProperty).Contains(name)//where 條件, orderBy: new List<IOrderBy> {//排序 f.OrderBy(source.Column(Chapter.NameProperty), OrderDirection.Ascending) } ); return (ChapterList)this.QueryData(q, pi); }
能夠看到,SqlTree 語法很是簡單:單元測試
更多的查詢語法示例,見本節後面的更多示例。學習
使用場景測試
當您處於如下場景時,須要使用 SqlTree 查詢:this
代碼段
RafySDK 中提供了兩個代碼段,來輔助開發者生成基本的 SqlTree 查詢結構:Rafy_Query、Rafy_Query_TableQueryContent。
詳情見:代碼段。
更多示例
下面將會列出一些常見的 SqlTree 查詢示例。經過這些代碼,您將學習到如何在各類查詢需求下使用 SqlTree。
基礎查詢:
[RepositoryQuery] public virtual ChapterList GetBy(string name, PagingInfo pi) { var f = QueryFactory.Instance; var t = f.Table<Chapter>(); var q = f.Query( //selection: f.SelectAll(),//沒有 selection,則默認表示查詢全部列 from: t,//要查詢的實體的表 where: t.Column(Chapter.NameProperty).Contains(name)//where 條件 ); return (ChapterList)this.QueryData(q, pi); }
表格數據查詢:
[RepositoryQuery] public virtual LiteDataTable GetBy(string name, PagingInfo pi) { var f = QueryFactory.Instance; var t = f.Table<Chapter>(); var q = f.Query( from: t, where: t.Column(Chapter.NameProperty).Contains(name) ); return this.QueryTable(q, pi);//由查詢實體變爲查詢數據表格,只是更換了這一行代碼。 }
兩個列的條件進行比較:
var table = f.Table(this);//使用當前的倉庫來表示當前的表 var q = f.Query( from :table, where: table.Column(Chapter.NameProperty).Equal(table.Column(Chapter.CodeProperty))//兩個列相等 );
使用 And、Or:
var table = f.Table(this); var q = f.Query( from :table, where: f.And( table.Column(Chapter.NameProperty).Equal(name), f.Or( table.Column(Chapter.IdProperty).LessEqual(10), table.Column(Chapter.IdProperty).GreaterEqual(1000) ) ) );
Join(SerialNumberValueRepository 中的真實代碼):
/// <summary> /// 獲取某個規則下最新的一個值。 /// </summary> /// <param name="autoCodeName"></param> /// <returns></returns> [RepositoryQuery] public virtual SerialNumberValue GetLastValue(string autoCodeName) { var f = QueryFactory.Instance; var t = f.Table<SerialNumberValue>(); var t2 = f.Table<SerialNumberInfo>(); var q = f.Query( from: t.Join(t2),//因爲 SerialNumberValue 有一個 SerialNumberInfo 的引用屬性,則在使用 Join 時,不須要給出 Join 的條件。 where: t2.Column(SerialNumberInfo.NameProperty).Equal(autoCodeName), orderBy: new List<IOrderBy> { f.OrderBy(t.Column(SerialNumberValue.LastUpdatedTimeProperty), OrderDirection.Descending) } ); return (SerialNumberValue)this.QueryData(q); }
使用完整的 Join:
var t = f.Table<SerialNumberValue>(); var t2 = f.Table<SerialNumberInfo>(); var q = f.Query( from: t.Join(t2, t.Column(SerialNumberValue.SerialNumberInfoIdProperty).Equal(t2.Column(SerialNumberInfo.IdProperty)), JoinType.Inner),//不但能夠給出具體的 Join 條件,還能夠給出 Join 類型。 where: t2.Column(SerialNumberInfo.NameProperty).Equal(autoCodeName), orderBy: new List<IOrderBy> { f.OrderBy(t.Column(SerialNumberValue.LastUpdatedTimeProperty), OrderDirection.Descending) } );
Exists:
var bookTable = f.Table(this); var chapterTable = f.Table<Chapter>(); var q = f.Query( from: bookTable, where: f.Exists(f.Query( from: chapterTable, where: chapterTable.Column(Chapter.BookIdProperty).Equal(bookTable.IdColumn) )) );
Not Exists:
var book = f.Table(this); var chapter = f.Table<Chapter>(); var q = f.Query( from: book, where: f.Not(f.Exists(f.Query( from: chapter, where: f.And( f.Constraint(chapter.Column(Chapter.BookIdProperty), book.IdColumn), f.Constraint(chapter.Column(Chapter.NameProperty), PropertyOperator.NotEqual, chapterName) ) ))) );
更多示例,請參照源碼中單元測試的 ORMTest 中的 TableQuery 相關方法。
PS:該文已經歸入《 Rafy 用戶手冊》中。