概述
之前在自定义ORMapping――关系表转换为实体或实体集合对象中提到过ORMapping的东西,在那片博客中也有ORMapping实现的一个简单思路,当时只实现了关系表转换为实体或实体集合这个功能,没有实现动态生成SQL这个部分,本片博客就是完善之前的那片博客,实现动态生成SQL语句这么一个功能。
实现思路
1、创建两个自定义特性,分别为表特性和字段特性,目的就是给相应的实体类的类名和属性名,打上相应的特性,从而创建类名和表名,属性和表字段名之间的对应关系
2、创建一个特性解析类,用来解析,这个实体类和表之间的对应关系,即获得这种对应关系
3、创建相应常量类和枚举,常量类用来生成相应的各种运算符或者排序时的关键字,枚举用来说明,生成字段对应的value是否需要添加引号
4、创建相应的where,order生成器类,用来添加相应的条件
5、创建一个整合类,将上面说的那些东西,整个为一个整体,生成相应的SQL语句,并且执行,并将返回的DataTable转换为集合对象
下面的每块内容就是相应的实现
自定义特性类
a、自定义特性的定义
///b、自定义特性的使用,使用在具体的一个实体类上,具体如下:/// 自定义字段特性 /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)] public class ORFieldMappingAttribute : Attribute { ////// 属性和字段的对应 /// /// 字段名称 /// 是否自增 /// 有没有逗号 public ORFieldMappingAttribute(string strFieldName, bool IsAutoIncreate = false, ORFieldValueHaveCommaEnum ORFieldValueHaveCommaEnum = ORFieldValueHaveCommaEnum.True) { this.strFieldName = strFieldName; this.ORFieldValueHaveCommaEnum = ORFieldValueHaveCommaEnum; this.IsAutoIncreate = IsAutoIncreate; } public string strFieldName { get; set; } public ORFieldValueHaveCommaEnum ORFieldValueHaveCommaEnum { get; set; } public bool IsAutoIncreate { get; set; } } ////// 自定义表特性 /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public class ORTableMappingAttribute : Attribute { ////// 类名和表明的对应 /// /// 表名 public ORTableMappingAttribute(string strTableName) { this.strTableName = strTableName; } public string strTableName { get; set; } }
[ORTableMapping("T_Users")]
public class User
{
[ORFieldMapping("Id",true,ORFieldValueHaveCommaEnum.False)]
public int UserId { get; set; }
[ORFieldMapping("Name",false,ORFieldValueHaveCommaEnum.True)]
public string UserName { get; set; }
[ORFieldMapping("Sex", false, ORFieldValueHaveCommaEnum.True)]
public string UserSex { get; set; }
[ORFieldMapping("Address", false, ORFieldValueHaveCommaEnum.True)]
public string Addr { get; set; }
[ORFieldMapping("Contents", false, ORFieldValueHaveCommaEnum.True)]
public string Content { get; set; }
}
解析自定义特性类
a、解析自定义特性类的代码如下
/// /// 获得实体的表名 ///
/// 实体的type对象
///
实体对象对应的表名
public static string GetTableName()
{
T obj = new T();
Type type = obj.GetType();
string strTableName="";
object[] Attarrs = type.GetCustomAttributes(false);
for (int i = 0; i < Attarrs.Length; i++)
{
if (Attarrs[i] is ORTableMappingAttribute)
{
ORTableMappingAttribute attribute = Attarrs[i] as ORTableMappingAttribute;
strTableName = attribute.strTableName;
}
}
return strTableName;
}
/// /// 获得实体属性对应的字段,并给字段赋值 ///
/// 实体的type对象
///
字典:key=字段名;value=字段值
public static Dictionary
GetFieldName(T obj) { Dictionary
dic = new Dictionary
(); Type type = obj.GetType(); PropertyInfo[] pis = type.GetProperties(); for (int i = 0; i < pis.Length; i++) { object[] Attarrs = pis[i].GetCustomAttributes(false); for (int j = 0; j < Attarrs.Length; j++) { if (Attarrs[j] is ORFieldMappingAttribute) { ORFieldMappingAttribute fn = Attarrs[j] as ORFieldMappingAttribute; if (fn.IsAutoIncreate != true) { if (fn.ORFieldValueHaveCommaEnum.ToString() == "True") { dic.Add(fn.strFieldName, "'" + pis[i].GetValue(obj, null).ToString() + "'"); } else { dic.Add(fn.strFieldName, pis[i].GetValue(obj, null).ToString()); } } } } } return dic; } }
该类是在生成SQL语句时使用的,只要你的实体类用上相应的特性,只要你把这个类型传递给这个解析类,他就可以给你解决出该类的类名和属性名,与数据库中的表名和字段名的对应关系
常量和枚举
定义如下常量和枚举类型
/// /// 逻辑运算符 ///
public class LogicOperatorConst
{
public const string And = "and";
public const string Or = "or";
public const string None = "";
}
/// /// 字段的排序方向定义 ///
public class FieldSortConst
{
public const string Asc = "asc";
public const string Desc = "desc";
}
/// /// 比较运算符 ///
public class CompareOperationConst
{
//条件项的运算符常量定义
public const string EqualTo = "=";
public const string GreaterThanOrEqualTo = ">=";
public const string GreaterThan = ">";
public const string LessThanOrEqualTo = "<=";
public const string LessThan = "<";
public const string NotEqualTo = "<>";
public const string Like = "LIKE";
public const string Is = "IS";
public const s