SmartPersistenceLayer 2.0 之Query進階查詢篇
總述
在看了前面的功能後,大家都會考慮到多表之間的查詢怎麼辦.在這裡,我想先講一下查詢在應用系統中的複雜性/重要性/可行性.
重要性:查詢統計是系統維護的一個目标之一,是系統的一個必不可少的部分,是以,在絕大部分的系統中,都會有查詢統計。
複雜性:查詢是在系統開發中一個最複雜的部分,誰都無法預料查詢統計的複雜性,哪怕是在一個小型系統中,是以,在SPL中也是無法實作這麼多的查詢統計,為了相容,SPL也努力實作了它所能做的,就是”聯合查詢”功能,将通過Query類來完成.
可行性:要能快速,有效的應付複雜多變的查詢與統計,在我看來,用視圖進行處理是一個最有效的方式.一是視圖的高速:資料庫的視圖查詢要比執行SQL來的快多,因為資料庫會為視圖進行緩存.二是開發快速性:寫SQL語句需要很多時間,而且查詢彙總的語句都是相當複雜的,是以也容易出錯,而視圖會把問題變的非常簡單,開發速度大大提高.三是維護性:由于查詢的複雜性,變動頻繁将是最明顯的特征,是以SQL語句的應變能力沒有視圖來得好.
是以,我的建議是對于一些查詢與統計,我們應盡可能的采用視圖來做.簡單的查詢當然可以使用SQL.現在來介紹SPL中的Query聯合查詢.
聯合查詢
例子:A表的ID與B表的AID有關聯,我們要關聯A/B表,選擇A表的NAME和B表的COMPANY值.
Query q1=new Query(typeof(A)); //建一個A表的Query
q1. AddAttribute(A.NAME); //添加一個要選擇的字段
Condition c=q1. GetQueryCondition(); //A表産生一個查詢
c.AddEqualTo(“Name”,”tintown”); //給A添加條件,請參考Condition
q1.OrderBy(“Name”); //添加一個排序,請參考RetrieveCriteria
Query q2=new Query(typeof(B)); //建一個B表的Query
q2.AddAttribute(B.COMPANY,”公司名”); //添加另一個選擇的字段,以别名輸出
q1. AddJoinQuery(A.ID,q2,B.AID); //把q1與q2關聯起來
DataTable dt=q1. Execute(); //執行查詢
步驟分析:
1. Query的建立與Criteira差不多一樣的,要指定一個實體類型typeof(A)
2. 由于是多表查詢,是以要求設定選擇哪些字段,目前SPL中有三種方式:
1. AddAttribute(字段名):這是直接以字段名為輸出名
2. AddAttribute(字段名,别名):這是可以把字段名以别名的方式輸出
3. AddAttribute(AttributeType.All):這是指以*号的方式全部顯示
3. 使用Execute()執行後傳回DataTable類型,可以直接綁定用。
在使用這種輸出字段時,要注意不能重名輸出,尤其是在使用了*号後,因為會正在一些不可預測的字段重名,是以,建議盡可能使用别名
通過以上的方式就可以實作大多數表之間的聯合查詢.以上有個局限性:表寫表之間的關系都是inner join的.也就是無法實作左連接配接效果,對于這種查詢,我還是建議使用視圖.
其他的Condition與OrderBy都與RetrieveCriteria類似,不再贅述。
統計查詢
對于彙總查詢本身也是非常複雜的,SPL也隻能實作簡單的彙總,對于複雜性的彙總還是建議使用視圖或是SQL進行.
Query q1=new Query(typeof(A));
q1.AddAttribute(A.NAME): //顯示NAME
q1.SelectMax(A.PRICE,”MAXPRICE”); //統計最高價格,别名MAXPRICE
q1.SelectSum(A.PRICE,”ALLPRICE”); //統計價格總和,别名ALLPRICE
q1.SelectAvg(A.PRICE,”AVGPRICE”); //統計平均價格,别名AVGPRICE
q1.SelectCount(A.NAME,”COUNT”); //統計條數,别名COUNT
q1.GroupBy(A.NAME); //接NAME進行分組
q1. Execute(); //執行
使用SelectMax,SelectSum,SelectAvg,SelectCount進行簡單的彙總,上面的例子是顯示多彙總值的情況,是以是采用Execute()方法.
SPL還提供了單傳回的方式:
Query q=newQuery(typeof(A);
q.SelectCount(A.ID);
intre=q. ExecuteScalar();
這可以傳回條數,其實在SPL中就是擷取第一條記錄的第一列值。
SQL語句執行
為了擴充相容性,還是要提供最基本的SQL語句執行接口,對于一些複雜的語句,可以使用SQL語句的執行來解決,實作的方式也是非常簡單:
string sqlString=”select name from A whereprice>1000”;
Query. ProcessSql(sqlString,”dbName”);
這裡的dbName 是指語句針對哪個資料源進行操作,當然要注意的,通過SQL執行傳回的字段名,是資料庫的實際的字段名了,而不是實體的屬性名了。
DISTINCT功能
在SPL中可以使用IsDistinct屬性來使用DISTINCT功能,這将最終生成”Select distinct…”的語句。
存儲過程
SPL中也同樣支援存儲過程,我們也可以通過Query的靜态類完成:
IDataParameterpara=Query.GetParameter("northwind"); //建立一個參數
para.ParameterName="@name1"; //定義參數名
para.Value="f"; //定義參數值