年前发布了一些文章,是关于.NET数据操作(点击查看)的。刚开始学习编程的时候,总感觉Java中的Hibernate 功能好强大,现在也不可否认它的确强大,特别是它在数据关系处理上,却是那样的让人称叹。
当我那时还不知道.net 中的Linq的时候,一直想自己能够简单的写个ORM映射框架。去年花费了几个月的业务时间终于算是整出来了,一些基本操作都能够实现了,自己号称从数据库操作冗余代码中解脱出来,其实自己很天真,那个框架是多么的不完善。总结了一下,最近超体力透支的准备将其扩展,同时也碰到了一下很头疼的问题,那就是那个实体的生成。
每次都要去受到生成那些代码,是一件非常消耗体力的事情,而李老师的动软代码生成器也不能生成我想要的代码,于是自己查阅了一些资料,写了一个自己需要的代码生成器,在此共享一下。
1.效果图
看东西总是效果图比较直接,首先看看这个代码生成器的效果图。
2.生成代码规则
因为这个实体是服务于自己写的框架,所以自己也规定了一些规则。相关文件可以参考本人 ORM映射解析 相关系列文章。这些文章代码太多,似乎有些难懂。这个框架正在升级版本中,后续继续讲解。
对于数据操作,制定了一系列特性,用于修饰实体类和实体的相关属性,这些特性能够很好的描述对象和数据库表之间的关系 。这个就是数据库和对象之间的桥梁,用特性建立他们之间的关系,用对象管理关系,用对象管理数据库表。
规则一:
[TableAttribute(DBName = "StuDB", Name = "Student", PrimaryKeyName = "Id", IsInternal = false)]
这个特性是用于描述实体类的,映射实体类和数据库表之间的关系。这里的特性定义暂不做讲解,将在后续文章中讲解。 先看看如下表格对此特性的描述
|
属性 |
作用 |
|
name |
数据表名 该字段用于描述数据库对应表的名称,而且该值最好与 数据表名大小写相同。该值有两种类型。 (1)直接自定表的名称 (2)[数据库名].[表名] 如果是(2)情况,则需要分割字符串,将数据库名分割 出来赋值给dBName |
|
dBName |
数据库名 该字段用于描述数据的名称,而且该值最好与 数据库名称大小写相同 |
|
primaryKeyName |
主键字段名 该实体必须指定对应数据库表的主键 |
|
information |
表实体描述信息 |
|
isInternal |
表实体是否国际化 默认为false |
|
version |
表实体版本号 默认为 "V1.0" |
规则二:
[ColumnAttribute(Name = "Id", IsPrimaryKey = true, AutoIncrement = true, DataType = DataType.Int, CanNull = false) 该特性是用于修饰属性的,该特性描述了数据库字段和实体对象属性之间的关系。
|
name |
表字段名称,该属性的值最好与数据表的字段的名称相同。 该字段的值有两种格式: (1) [表名].[字段名] (2) [字段名] 如果该字段的值为(1)情况,则应分割字符串,将字段名 赋值给name属性,表名则赋值给tableName |
|
tableName |
表字段对应表名称 该值是可以为空的,如果name的值的情况满足(1)情况, 可以分割的值赋值给该属性 |
|
dataType |
表字段的数据类型 该属性的类型为自定义类型,该字段是一个枚举类型。 该字段描述了25中数据类型 |
|
length |
表字段的长度 控制该字段对应的数据库表字段值的最大长度 可以不指定该值 |
|
canNull |
表字段是否可以为空 true 可以为空 false 不能为空 |
|
defaultValue |
表字段的默认值 默认情况为null |
|
isPrimaryKey |
表字段是否为主键 true 为主键 false 不是外键 |
|
autoIncrement |
表字段是否为自动增长列 true 是自动增长列 false 不是自动增长列 |
|
isUnique |
确定某个字段是否唯一 true 是唯一的 false 不是唯一 |
|
regularExpress |
表字段的匹配规则 字段匹配规则正则表达式 |
|
isForeignKey |
表字段是否为外键 true 为外键 false 不是外键 |
|
foreignTabName |
表字段外键对应的表名称 如果isForeignKey 为true,则需要指定其值 |
|
information |
表字段的描述信息 |
|
|
|
3. 生成代码展示
代码
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using CommonData.Entity;
6 using CommonData.Model.Core;
7
8 namespace Entity.School
9 {
10 [TableAttribute(DBName = "StuDB", Name = "Student", PrimaryKeyName = "Id", IsInternal = false)]
11 public class Student:BaseEntity
12 {
13 public Student()
14 {
15 }
16
17 private int id;
18
19 [ColumnAttribute(Name = "Id", IsPrimaryKey = true, AutoIncrement = true, DataType = DataType.Int, CanNull = false)]
20 public int Id
21 {
22 get { return id; }
23 set { id = value; }
24 }
25
26 private string sname;
27
28 [ColumnAttribute(Name = "Sname", IsPrimaryKey = false, AutoIncrement = false, DataType = DataType.Nvarchar, CanNull = false)]
29 public string Sname
30 {
31 get { return sname; }
32 set { sname = value; }
33 }
34
35 private string sex;
36
37 [ColumnAttribute(Name = "Sex", IsPrimaryKey = false, AutoIncrement = false, DataType = DataType.Nvarchar, CanNull = false)]
38 public string Sex
39 {
40 get { return sex; }
41 set { sex = value; }
42 }
43
44 private DateTime birthday;
45
46 [ColumnAttribute(Name = "Birthday", IsPrimaryKey = false, AutoIncrement = false, DataType = DataType.Datetime, CanNull = false)]
47 public DateTime Birthday
48 {
49 get { return birthday; }
50 set { birthday = value; }
51 }
52
53 private string addr;
54
55 [ColumnAttribute(Name = "Addr", IsPrimaryKey = false, AutoIncrement = false, DataType = DataType.Nvarchar, CanNull = false)]
56 public string Addr
57 {
58 get { return addr; }
59 set { addr = value; }
60 }
61
62 private string telephone;
63
64 [ColumnAttribute(Name = "Telephone", IsPrimaryKey = false, AutoIncrement = false, DataType = DataType.Nvarchar, CanNull = false)]
65 public string Telephone
66 {
67 get { return telephone; }
68 set { telephone = value; }
69 }
70 }
71 }
72
其实生成代码很简单,写文件而已。生成一个实体也很简答,查询一下数据库知道数据表有多少个字段以及字段的名称即可。但是这里的实体不仅仅是我们看到的实体那么简单。这个实体描述了数据库表,数据库表字段的属性信息。要生成这样的一个实体并不简单。当大多数人去研究对数据库操作的时候,眼前要实现的功能迷惑了我们的心智,数据操作还有更多不为人知的东西却被我们悄悄的丢弃。下面我们简单的介绍几个数据库系统操作的sql语句,让我们也感受一下代码生成器的神秘之处。
(a).获取数据库服务名
代码
2 {
3 DataTable tableDataSouce=SqlClientFactory.Instance.CreateDataSourceEnumerator().GetDataSources();
4 IList<string> listServerName = new List<string>();
5 for (int i = 0; i < tableDataSouce.Rows.Count; i++)
6 {
7 listServerName.Add(tableDataSouce.Rows[i]["ServerName"].ToString()+"\\"+tableDataSouce.Rows[i]["InstanceName"].ToString());
8 }
9 return listServerName;
10 }
我们是使用客户端连接数据库服务器的,在System.Data.SqlClient中为为我们提供了一个实例,来获得服务器的名称和数据库实例。SqlClientFactory.Instance.CreateDataSourceEnumerator().GetDataSources() 这个方法能够返回一个DataTable实例,这个DataTable 中就包含了数据库服务名称和数据库实例。tableDataSouce.Rows[i]["ServerName"]就是客户端能够获取的服务名称,tableDataSouce.Rows[i]["InstanceName"]能够获取数据库实例的名称。
(b).获得服务器上的数据库名称
2 {
3 using (IDbProvider provider = new SqlProvider())
4 {
5 if (string.IsNullOrEmpty(userid) && string.IsNullOrEmpty(password))
6 {
7 provider.ConnectionString = "server=" + servername + ";database=master;Integrated Security=true";
8 }
9 else
10 {
11 provider.ConnectionString = "server=" + servername + ";database=master;uid=" + userid + ";pwd=" + password;
12 }
13 IBaseHelper baseHelper = new BaseHelper();
14 string sql="select name from sysdatabases where dbid>4";
15 return baseHelper.ExecuteTable(provider,sql);
16 }
17 }