SuperHelper是博主利用業余時間編寫的一個ORM微型框架,除了可以提高開發效率,與其它ORM框架相比,博主更加喜歡SuperHelper的使用簡單、適用范圍廣的特點。
簡介
SuperHelper是一個基於.Net平台的非侵入式的的微型ORM框架,可幫助開發者快速簡便的訪問數據庫並對其操作,且部署起來十分簡單;只依賴於相應的數據庫引擎,開發者可以根據實際項目需要增加引用不同版本的SuperHelper組件,且不會產生沖突。(目前SuperHelper有SQlServer版和SQLite版)
以下是SuperHelper的概要特點:
1、部署十分簡單。開發者只需在項目配置文件中為SuperHelper指定一個可用的連接字符串即可完成部署。
2、適用范圍廣。SuperHelper可以在經典三層架構項目、一般處理程序+模板引擎項目、WebForm、MVC架構項目等等都可以使用,項目中如果需要切換使用不同數據庫引擎則只需切換相應版本的SuperHelper組件即可。還有,SuperHelper可以與其它ORM框架如微軟的EF、NHibernate等混可使用且不會產生任何沖突。同時因為SuperHelper是一個非侵入式的ORM框架,項目不會對SuperHelper有過多的依賴,開發者依然可以把代碼很方便的遷移到其他地方。
3、使用靈活。寫好sql語句之后,開發者只需要再寫一行代碼即可完成訪問數據庫並返回相應數據實體的操作(SuperHelper還支持對實體類的復雜類型屬性或字段賦值)。ps:與一些微型ORM一樣,SuperHelper是不支持LinQ的,不過針對SQlServer,SuperHelper支持存儲過程的調用。
使用方法
下面的使用方法介紹中,如無特別說明,皆以SuperHelper的SQlServer版本為例。
1、部署:
首先在項目的配置文件中為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組件即可。
2、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/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。