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/
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。