SuperHelper是博主利用業餘時間編寫的一個ORM微型框架,除了能夠提升開發效率,與其它ORM框架相比,博主更加喜歡SuperHelper的使用簡單、適用範圍廣的特色。git
簡介程序員
SuperHelper是一個基於.Net平臺的非侵入式的的微型ORM框架,可幫助開發者快速簡便的訪問數據庫並對其操做,且部署起來十分簡單;只依賴於相應的數據庫引擎,開發者能夠根據實際項目須要增長引用不一樣版本的SuperHelper組件,且不會產生衝突。(目前SuperHelper有SQlServer版和SQLite版)github
如下是SuperHelper的概要特色:sql
一、部署十分簡單。開發者只需在項目配置文件中爲SuperHelper指定一個可用的鏈接字符串便可完成部署。數據庫
二、適用範圍廣。SuperHelper能夠在經典三層架構項目、通常處理程序+模板引擎項目、WebForm、MVC架構項目等等均可以使用,項目中若是須要切換使用不一樣數據庫引擎則只需切換相應版本的SuperHelper組件便可。還有,SuperHelper能夠與其它ORM框架如微軟的EF、NHibernate等混可以使用且不會產生任何衝突。同時由於SuperHelper是一個非侵入式的ORM框架,項目不會對SuperHelper有過多的依賴,開發者依然能夠把代碼很方便的遷移到其餘地方。架構
三、使用靈活。寫好sql語句以後,開發者只須要再寫一行代碼便可完成訪問數據庫並返回相應數據實體的操做(SuperHelper還支持對實體類的複雜類型屬性或字段賦值)。ps:與一些微型ORM同樣,SuperHelper是不支持LinQ的,不過針對SQlServer,SuperHelper支持存儲過程的調用。框架
使用方法ide
下面的使用方法介紹中,如無特別說明,皆以SuperHelper的SQlServer版本爲例。學習
一、部署:測試
首先在項目的配置文件中爲SuperHelper指定一條可用的數據庫鏈接字符串,將其Name屬性設置爲「SuperHelper_SQLServer」,以下代碼所示。(這裏是根據不一樣版本的SuperHelper組件的命名空間決定,若是使用SuperHelper的SQLite版,則Name屬性應爲「SuperHelper_SQLite」)。
<connectionStrings> <add name="SuperHelper_SQLServer" connectionString="Data Source=127.0.0.1;Initial Catalog=News;Integrated Security=True"/> </connectionStrings>
至此,SuperHelper的部署工做就已經完成了,接下來,只須要在解決方案的某個項目中添加引用SuperHelper_SQLServer組件便可。
二、SuperHelper的方法調用
對於SuperHelper而言,全部數據庫訪問操做分爲兩種:查詢、非查詢(增,刪、改)。
爲了演示方便,博主準備一個測試用的新聞數據庫News和相應的實體類,若是你們習慣使用本身數據庫來測試,則能夠跳過準備過程,直接看代碼。
下面是News數據庫的sql語句腳本,用於生成該數據庫的架構和少許的測試數據。
1 CREATE DATABASE [News] 2 CONTAINMENT = NONE 3 ON PRIMARY 4 ( NAME = N'News', FILENAME = N'此處要改成本地路徑\News.mdf' , SIZE = 5120KB , MAXSIZE = 10240KB , FILEGROWTH = 1024KB ) 5 LOG ON 6 ( NAME = N'News_log', FILENAME = N'此處要改成本地路徑\News.ldf' , SIZE = 2048KB , MAXSIZE = 10240KB , FILEGROWTH = 3072KB ) 7 8 USE [News] 9 CREATE TABLE [dbo].[NewsInfo]( 10 [NewsID] [int] IDENTITY(1,1) NOT NULL, 11 [NewsTitle] [nvarchar](50) NULL, 12 [SubTime] [datetime] NULL, 13 [TypeID] [int] NULL, 14 [NewsContent] [nvarchar](max) NULL 15 ) 16 17 18 CREATE TABLE [dbo].[TypeInfo]( 19 [TypeID] [int] IDENTITY(1,1) NOT NULL, 20 [TypeTitle] [nvarchar](50) NULL 21 ) 22 23 USE [News] 24 GO 25 SET IDENTITY_INSERT [dbo].[NewsInfo] ON 26 27 GO 28 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (1, N'測試', CAST(N'2014-10-30 00:00:00.000' AS DateTime), 1, N'測試文檔') 29 GO 30 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (2, N'測試123', CAST(N'2013-05-06 00:00:00.000' AS DateTime), 2, N'這是一張大圖') 31 GO 32 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (3, N'test456', CAST(N'2013-06-07 00:00:00.000' AS DateTime), 3, N'545616516') 33 GO 34 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (5, N'你好', CAST(N'2014-05-06 00:00:00.000' AS DateTime), 2, N'sdfvszgvsz') 35 GO 36 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (6, N'APEC', CAST(N'2013-08-06 00:00:00.000' AS DateTime), 1, N'354asefsef65') 37 GO 38 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (7, N'hahahah', CAST(N'2014-06-08 00:00:00.000' AS DateTime), 2, N'srgdfs') 39 GO 40 INSERT [dbo].[NewsInfo] ([NewsID], [NewsTitle], [SubTime], [TypeID], [NewsContent]) VALUES (8, N'weqwe', CAST(N'2012-01-05 00:00:00.000' AS DateTime), 4, N'5465dfsdfv') 41 GO 42 SET IDENTITY_INSERT [dbo].[NewsInfo] OFF 43 GO 44 SET IDENTITY_INSERT [dbo].[TypeInfo] ON 45 46 GO 47 INSERT [dbo].[TypeInfo] ([TypeID], [TypeTitle]) VALUES (1, N'文字') 48 GO 49 INSERT [dbo].[TypeInfo] ([TypeID], [TypeTitle]) VALUES (2, N'圖片') 50 GO 51 INSERT [dbo].[TypeInfo] ([TypeID], [TypeTitle]) VALUES (3, N'視頻') 52 GO 53 INSERT [dbo].[TypeInfo] ([TypeID], [TypeTitle]) VALUES (4, N'音頻') 54 GO 55 SET IDENTITY_INSERT [dbo].[TypeInfo] OFF 56 GO
數據庫準備完成後,接下來是準備相應的數據庫實體類。
1 public class NewsInfo 2 { 3 public int NewsID { get; set; } 4 public string NewsTitle { get; set; } 5 public DateTime SubTime { get; set; } 6 public int TypeID { get; set; } 7 public string NewsContent { get; set; } 8 } 9 10 public class TypeInfo 11 { 12 public int TypeID { get; set; } 13 public string TypeTitle { get; set; } 14 }
至此,準備過程已完成,下面咱們先來執行一條簡單的sql語句。
1 using SuperHelper_SQLServer; 2 3 namespace SuperHelper演示demo 4 { 5 public partial class Form1 : Form 6 { 7 public Form1() 8 { 9 InitializeComponent(); 10 } 11 12 private void Form1_Load(object sender, EventArgs e) 13 { 14 string sql = "select * from NewsInfo"; 15 16 List<NewsInfo> lst_news = SH_Query<NewsInfo>.GetListBySql(sql); 17 18 dgv.DataSource = lst_news; 19 } 20 } 21 }
接下來,咱們再來執行有參數的sql語句。(重複的代碼,博主就再也不貼出來,只貼關鍵的sql語句和執行代碼)
1 //查詢NewsID=1 和 TypeID=2 的新聞信息 2 3 #region 這是第一種寫法 4 string sql = "select * from NewsInfo where NewsID = @NewsID and TypeID = @TypeID"; 5 NewsInfo newinfo = new NewsInfo(); 6 newinfo.NewsID = 1;
newinfo.TypeID = 2;
7 8 List<NewsInfo> lst_news = SH_Query<NewsInfo>.GetListBySql(sql, new List<object> { newinfo}); 9 #endregion 10 11 #region 這是第二種寫法 12 string sql = "select * from NewsInfo where NewsID = @a and TypeID = @b"; 13 int i = 1;
int j = 2; 14 15 List<NewsInfo> lst_news = SH_Query<NewsInfo>.GetListBySql(sql, new List<object> { i, j }); 16 #endregion
看到這裏,估計你們也能對SuperHelper的用法和原理有大概的認識了。
SuperHelper實際上是根據匹配實體類的公共屬性或者公共字段名稱與執行sql語句的查詢結果集中的列名稱來產生映射關係;因此,若是實體類的屬性或者字段名與sql語句查詢的結果集的列名不一致(名稱大小寫也必須一致),那麼就沒法正確獲取數據了。根據上面的代碼舉個例子:若是NewsInfo類中的NewsTitle屬性改成newsinfo,而News數據庫中NewsInfo表的NewsTitle列名保持不變,而由於上述sql語句執行後的結果集列名中只有「NewsTitle」而沒有「newsinfo」,因此最終結果就是lst_news中的對象的NewsTitle屬性都爲空。
至於sql語句的參數匹配方式,你們能夠參考下面的兩種方法。
第一種寫法:根據實體類對象的屬性或者字段名與sql語句中的參數名進行匹配。一樣的,根據上面的第一種寫法代碼舉個例子:sql語句中的@NewsID必須與實體類對象newsinfo的屬性名NewsID大小寫一致,這樣才能1賦值給參數@NewsID。
第二種寫法:根據參數順序匹配。一樣的,根據上面的第二種寫法代碼舉個例子:i 的值會賦給sql語句中第一個出現的參數,而無論參數@a改爲什麼名字。若是sql語句中同一個參數出現屢次,則以該參數第一次出現的位置爲準,例如sql語句是這樣「..@b.....@a.....@b...@c....」,則參數集合new List<object>{i, j, k}中 i 會賦值給@b,j 賦值給@a,k 賦值給@c。
其實,上述兩種匹配方法是能夠混合使用的,由此能夠得出第三種寫法,代碼以下:
1 //查詢NewsID=1 和 TypeID = 2 的新聞信息 2 3 string sql = "select * from NewsInfo where NewsID = @NewsID and TypeID = @a"; 4 5 NewsInfo newinfo = new NewsInfo(); 6 newinfo.NewsID = 1; 7 int i = 2; 8 9 List<NewsInfo> lst_news = SH_Query<NewsInfo>.GetListBySql(sql, new List<object> { newinfo, i});
SuperHelper會優先根據實體類的屬性與字段與sql語句中的參數進行匹配,而剩下的沒法與實體類匹配成功的參數則按照順序來進行二次匹配(ps:已經與實體類匹配好的sql參數不會參加二次匹配的排序)
上面簡介中還提到,SuperHelper還支持對實體類的複雜類型屬性或字段賦值,爲了演示這個功能,咱們須要對上述NewsInfo類中添加一個class類型的屬性,完整NewsInfo定義以下:
1 public class NewsInfo 2 { 3 public int NewsID { get; set; } 4 public string NewsTitle { get; set; } 5 public DateTime SubTime { get; set; } 6 public int TypeID { get; set; } 7 public string NewsContent { get; set; } 8 9 public TypeInfo Ti { get; set; } //TypeInfo類是上面準備過程當中定義好的類 10 }
對於這個TypeInfo類型的屬性Ti,即便數據庫中NewsInfo表中也含有名稱爲Ti的列,使用上述提到的sql語句是沒辦法完成數據獲取的,須要對其sql語句進行稍加修改,代碼以下:
1 //對實體類中的複雜屬性或字段進行數據匹配 2 3 string sql = "select NewsID,NewsTitle,NewsContent,TypeTitle as [Ti.TypeTitle] from NewsInfo left join TypeInfo on NewsInfo.TypeID=TypeInfo.TypeID"; 4 5 List<NewsInfo> lst_news = SH_Query<NewsInfo>.GetListBySql(sql);
此時,你們能夠斷點調試,查看lst_news中NewsInfo對象中Ti屬性中的TypeTitle屬性賦值已經成功了。其實整個修改過程也很簡單,就是將查詢結果集中的列名「TypeTitle」改爲「Ti.TypeTitle」便可。這就跟你在VS中寫代碼同樣,想要獲取某個類的屬性時,只需用「.」就能夠獲取到了,意思是同樣的。固然,若是Ti中也含有class類型的屬性或字段時,能夠繼續以「.」方式對其進行賦值,如:「Ti.class類型的屬性名或字段名.class類型的屬性名或字段名.class類型的屬性名或字段名」,以此類推。
至此,SuperHelper中主要的查詢方法的使用要點已經基本介紹完畢了,至於非查詢的方法使用與查詢方法基本一致,只不過非查詢固定返回值是受影響行數而已。固然,SuperHelper中還有支持臨時切換訪問不一樣數據庫,SQLServer版還支持存儲過程等等。但博文篇幅有限,在此就很少詳述了,有時間的話博主會再詳細寫其它用法。
SuperHelper源碼地址:https://github.com/honker-bin/SuperHelper
最後再說幾句話,博主不是什麼技術大牛,可是大牛之因此是大牛,除了技術牛X以外,善於分享是他們共同的特色。其實不少程序員朋友在長期的開發過程積累了很多有用的技術與經驗,不是不想分享,而是懶得分享,可是要知道,技術除了不斷學習,分享和交流也是迅速提升自身的捷徑之一(這一點博主深有體會)。最後調侃一下,這年頭連微軟都開源了,你還懶得分享本身的技術經驗嗎?:)
做者:馮禮斌
文章出處:http://www.cnblogs.com/fenglibin/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。