最最简单的ORM模块(一)
虽说ORM框架也挺多……但是说来惭愧我并没有在项目中真正用过……,最近想认认真真研究一下
.NET的反射,所以就有一个想写个框架的念头,小弟我从07年毕业一直做.NET平台的软件开发,但是从
09年初才开始接触到一些设计模式、设计思想。而且我打算逐步的记录自己是如何修改这个框架的。
好了,现在进入正题,现在先仅仅实现一个简单的关系映射,可以取得数据库的数据,以后再慢慢重
构。
准备工作:数据库,表
1 CREATE TABLE [dbo].[Man](
2 [ManID] [varchar](50) NOT NULL,
3 [ManName] [nvarchar](max) NOT NULL,
4 [ManAge] [nvarchar](max) NOT NULL,
5 CONSTRAINT [PK_Man] PRIMARY KEY CLUSTERED
6 (
7 [ManID] ASC
8 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
9 ) ON [PRIMARY]
2 [ManID] [varchar](50) NOT NULL,
3 [ManName] [nvarchar](max) NOT NULL,
4 [ManAge] [nvarchar](max) NOT NULL,
5 CONSTRAINT [PK_Man] PRIMARY KEY CLUSTERED
6 (
7 [ManID] ASC
8 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
9 ) ON [PRIMARY]
插入两条数据:
然后现在要做的就是可以取出所有的数据。
既然要实现最简单的最少需要两个功能,一是封装数据库操作,二是实体类与表的关系映射、类属性与
表中字段的映射。对于这种关系映射没有比反射更合适的了。现在就构造两个类来分别映射表与表中的
字段。
1 //映射表
2 public class TableAttribute:Attribute
3 {
4 public string TableName;
5
6 public TableAttribute(string tableName)
7 {
8 this.TableName = tableName;
9 }
10 }
11 //映射表中的字段,暂时不考虑数据类型对应的问题。
12 public class FieldAttribute : Attribute
13 {
14
15 public string FieldName;
16
17 public FieldAttribute(string fieldName)
18 {
19 this.FieldName = fieldName;
20 }
21
22 }
23
2 public class TableAttribute:Attribute
3 {
4 public string TableName;
5
6 public TableAttribute(string tableName)
7 {
8 this.TableName = tableName;
9 }
10 }
11 //映射表中的字段,暂时不考虑数据类型对应的问题。
12 public class FieldAttribute : Attribute
13 {
14
15 public string FieldName;
16
17 public FieldAttribute(string fieldName)
18 {
19 this.FieldName = fieldName;
20 }
21
22 }
23
封装的数据库操作类:
代码
public class DBHelper
{
public static SqlConnection myConn;
public DBHelper(string connectionString)
{
myConn = new SqlConnection(connectionString);
}
public static SqlDataReader ExecuteReader(string sql)
{
myConn.Open();
SqlCommand cmd = new SqlCommand(sql, myConn);
SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return sdr;
}
}
{
public static SqlConnection myConn;
public DBHelper(string connectionString)
{
myConn = new SqlConnection(connectionString);
}
public static SqlDataReader ExecuteReader(string sql)
{
myConn.Open();
SqlCommand cmd = new SqlCommand(sql, myConn);
SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return sdr;
}
}
实现关系映射的类(核心部分):
1 public class ActiverRecord
2 {
3
4
5 public List<ActiverRecord> GetAllRecord()
6 {
7 List<ActiverRecord> listProduct = new List<ActiverRecord>();
8
9 ActiverRecord stanceObj = this;
10
11
12 //拼接SQL语句
13 string tableName = "";
14 object [] attrbuteArray = this.GetType().GetCustomAttributes(true);
15
16 tableName = ((attrbuteArray[0]) as TableAttribute).TableName;
17 string sql = "SELECT * FROM " + tableName;
18
19
20 //取得对应关系
21 Dictionary<string, string> realiationShip = new Dictionary<string, string>();
22
23 foreach (PropertyInfo pInfo in this.GetType().GetProperties())
24 {
25 string PropertyName = pInfo.Name;
26 string FildName = ((FieldAttribute)pInfo.GetCustomAttributes(true)[0]).FieldName;
27 realiationShip.Add(PropertyName, FildName);
28 }
29 Assembly assemble = Assembly.GetAssembly(this.GetType());
30 using (SqlDataReader sdr =DBHelper.ExecuteReader(sql))
31 {
32 while (sdr.Read())
33 {
34 object manOne=assemble.CreateInstance(this.GetType().FullName);
35 int i = 0;
36 foreach (PropertyInfo pOne in manOne.GetType().GetProperties())
37 {
38 foreach (object attr in pOne.GetCustomAttributes(true))
39 {
40 string filedName = ((FieldAttribute)attr).FieldName;
41 pOne.SetValue(manOne, sdr[filedName], null);
42 i++;
43 }
44 }
45
46 listProduct.Add((ActiverRecord)manOne);
47
48 }
49 }
50
51 return listProduct;
52 }
53 }
2 {
3
4
5 public List<ActiverRecord> GetAllRecord()
6 {
7 List<ActiverRecord> listProduct = new List<ActiverRecord>();
8
9 ActiverRecord stanceObj = this;
10
11
12 //拼接SQL语句
13 string tableName = "";
14 object [] attrbuteArray = this.GetType().GetCustomAttributes(true);
15
16 tableName = ((attrbuteArray[0]) as TableAttribute).TableName;
17 string sql = "SELECT * FROM " + tableName;
18
19
20 //取得对应关系
21 Dictionary<string, string> realiationShip = new Dictionary<string, string>();
22
23 foreach (PropertyInfo pInfo in this.GetType().GetProperties())
24 {
25 string PropertyName = pInfo.Name;
26 string FildName = ((FieldAttribute)pInfo.GetCustomAttributes(true)[0]).FieldName;
27 realiationShip.Add(PropertyName, FildName);
28 }
29 Assembly assemble = Assembly.GetAssembly(this.GetType());
30 using (SqlDataReader sdr =DBHelper.ExecuteReader(sql))
31 {
32 while (sdr.Read())
33 {
34 object manOne=assemble.CreateInstance(this.GetType().FullName);
35 int i = 0;
36 foreach (PropertyInfo pOne in manOne.GetType().GetProperties())
37 {
38 foreach (object attr in pOne.GetCustomAttributes(true))
39 {
40 string filedName = ((FieldAttribute)attr).FieldName;
41 pOne.SetValue(manOne, sdr[filedName], null);
42 i++;
43 }
44 }
45
46 listProduct.Add((ActiverRecord)manOne);
47
48 }
49 }
50
51 return listProduct;
52 }
53 }
对该模块的使用:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 DBHelper dbop = new DBHelper("Data Source=.;Initial Catalog=TestCode;User ID=sa;Password=sa");
6
7 Man man = new Man();
8 List<ActiverRecord> onelist= man.GetAllRecord();
9 foreach (ActiverRecord one in onelist)
10 {
11 Man oneP = (Man)one;
12 Console.WriteLine("{0} {1} {2}",oneP.ManID,oneP.ManName,oneP.ManID);
13 }
14 }
15 }
16
17 [Table("dbo.Man")]
18 public class Man: ActiverRecord
19 {
20 private string _manID;
21
22 [Field("ManID")]
23 public string ManID
24 {
25 get { return _manID; }
26 set { _manID = value; }
27 }
28 private string _manName;
29 [Field("ManName")]
30 public string ManName
31 {
32 get { return _manName; }
33 set { _manName = value; }
34 }
35 private string _ManAge;
36
37 [Field("ManAge")]
38 public string ManAge
39 {
40 get { return _ManAge; }
41 set { _ManAge = value; }
42 }
43
44 }
2 {
3 static void Main(string[] args)
4 {
5 DBHelper dbop = new DBHelper("Data Source=.;Initial Catalog=TestCode;User ID=sa;Password=sa");
6
7 Man man = new Man();
8 List<ActiverRecord> onelist= man.GetAllRecord();
9 foreach (ActiverRecord one in onelist)
10 {
11 Man oneP = (Man)one;
12 Console.WriteLine("{0} {1} {2}",oneP.ManID,oneP.ManName,oneP.ManID);
13 }
14 }
15 }
16
17 [Table("dbo.Man")]
18 public class Man: ActiverRecord
19 {
20 private string _manID;
21
22 [Field("ManID")]
23 public string ManID
24 {
25 get { return _manID; }
26 set { _manID = value; }
27 }
28 private string _manName;
29 [Field("ManName")]
30 public string ManName
31 {
32 get { return _manName; }
33 set { _manName = value; }
34 }
35 private string _ManAge;
36
37 [Field("ManAge")]
38 public string ManAge
39 {
40 get { return _ManAge; }
41 set { _ManAge = value; }
42 }
43
44 }
运行后的输出结果:
这恐怕是简单的的不能再简单实现映射的模块了。
下一次重构的目标:
1.实现简单的基本的CRUD功能。
2.可以实现生成所需SQL的功能。
3.使用泛型来避免不必要的类型转换。
4.希望可以实现类型之间的对应,但是目前还没想到什么好的办法。(望高手赐教!)
小弟我才学疏浅,对于下一步的重构希望高手可以提出建议。