Gadgets 是我单独写的一个简单的ORM数据持久层,由于能力有限,功能并不强大,不过还算能满足我现在的需求。随之日后需求的更改,我也会慢慢给Gadgets添加功能,以及完成目前部分不足之处。好了,不废话了,进入正题。
Gadgets 用的是类似LINQ的方式去实现,例如:
View Code
1 GadgetsSelect<User> gadgets = new GadgetsSelect<User>();
2 gadgets.Select(u => new { u.UserId, u.UserName }).Where(u => u.UserId < 10);
3 DataSet ds = gadgets.GetDataSet();
4 Console.ReadLine();
5
6
7 [Table(TableName="T_User")]
8 public class User:GadgetsEntityBase
9 {
10 [Field(FieldName = "F_UserId", TableName = "T_User",SqlDbType=SqlDbType.Int,IsPrimaryKey=true)]
11 public Int32 UserId { get; set; }
12 [Field(FieldName = "F_UserName", TableName = "T_User", SqlDbType = SqlDbType.NVarChar)]
13 public string UserName { get; set; }
14 }
15 [Table(TableName = "T_Admin")]
16 public class Admin : GadgetsEntityBase
17 {
18 [Field(FieldName = "F_AdminId", TableName = "T_Admin", SqlDbType = SqlDbType.Int, IsPrimaryKey = true)]
19 public Int32 AdminId { get; set; }
20 [Field(FieldName = "F_AdminName", TableName = "T_Admin", SqlDbType = SqlDbType.NVarChar)]
21 public string AdminName { get; set; }
22 [Field(FieldName = "F_UserId", TableName = "T_User", SqlDbType = SqlDbType.Int,IsForeignKey=true)]
23 public int UserId { get; set; }
24 }
其中 User,Admin为实体类,
gadgets.Select(u => new { u.UserId, u.UserName }).Where(u => u.UserId < 10);
这段代码将生成一条SQL,生成的结果是:
SELECT [T_User].[F_UserId],[T_User].[F_UserName] FROM [T_User] WHERE [T_User].[F_UserId]<'10'
GetDataSet是将生成的SQL语句执行,并返回一个一个DataSet,里面还支持返回一个List<object> object对象则就是你进行查询后生成的一个匿名类。
例如上面的查询语句,返回的是F_UserId,F_UserName 2列数据,那么object对象则就是一个含有F_UserId,F_UserName作为属性的一个匿名类型,例如:
一些开发中经常用到的功能,例如,skip功能,select top count 这样的分页查询方式
View Code
1 GadgetsSelect<User> gadgets = new GadgetsSelect<User>();
2 gadgets.Select(u => new { u.UserId, u.UserName }).CharIndex(u => u.UserName == "D").Skip(1, u => u.UserId > 2, false)
3 .Where(u => u.UserId >2);
生成的SQL语句是:
1 SELECT [T_User].[F_UserId],[T_User].[F_UserName] FROM [T_User]
WHERE [T_User].[F_UserId] NOT IN (
SELECT TOP 1 [T_User].[F_UserId] FROM T_User WHERE [T_User].[F_UserId]>'2' )
AND [T_User].[F_UserId]>'2' AND CHARINDEX('D',[T_User].[F_UserName])>0
前面说的都是写简单例子,目前支持多表查询,JOIN等等一些经常用到的功能。
部分我尚为经常用到的功能,我就还没有去实现,例如,事物。不过,我会慢慢添加进去。
好了,基本演示代码已经写完了,接下来,说的是,我是如何完成的吧。
首先,从实体类开始讲起,实体类上面打了很多我自定义特征,为的是在反射的过程中可以获取部分我需要的数据,例如表名称,字段名称等等。
1 [Table(TableName="T_User")]
2 public class User:GadgetsEntityBase
3 {
4 [Field(FieldName = "F_UserId", TableName = "T_User",SqlDbType=SqlDbType.Int,IsPrimaryKey=true)]
5 public Int32 UserId { get; set; }
6 [Field(FieldName = "F_UserName", TableName = "T_User", SqlDbType = SqlDbType.NVarChar)]
7 public string UserName { get; set; }
8 }
GadgetsEntityBase 是那些需要进行反射的实体类的基类,换句话说,没有继承该基类,则无法对该对象进行操作。
Table,Field是我自定义的特征,没什么好说的。重点在于
public Int32 UserId { get; set; } 这里的Int32 int 跟Int32 在我们认识的范畴里面,其实是一样的。但是,这真是我目前的一点点小缺陷,由于我在将SqlDbType.Int转换为C#对于的类型过程中,他
是直接转为Int32 而int跟Int32却不是相同的。所以,例如,你将Int32改成int,在生成SQL语句的时候,就会报错或者直接忽略该属性。不过,我会在后面慢慢修改过来。
在Select的过程中,你只需要传入一条lambda表达式,然后我就可以根据表达式进行查询你需求的数据。但是目前支持
select(()=>new{})用new的方式传入一个匿名对象,部分功能可以支持传入select(u=>u)这个参数对象。后面将会慢慢扩展开来。
值得一提的是,我使用了自定义缓存,在反射,序列化XML等操作上,性能是比较客观的。部分代码是参考老赵而来,他的文章也给了我不少提示,在此谢谢他。
接下来我也不知道说写什么,现在就直接贴源码,有兴趣的朋友可以下载去看看。有什么高见,我有什么地方写的不好,麻烦大家指出来哦。
下载地址:https://files.cnblogs.com/suguicheng/2011-7-28.rar