通过配置实体与表的关系映射后,就可以实现对表的操作了,接下来实现简单对象的新增功能。下面代码1-1是定义的操作数据对象方法的接口:
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.SqlClient; System.Orm.EntityManager { public { Transaction { get; set; }
<T> FindAll<T>() where T : ();
<T> FindBySql<T>( strSql) where T : ();
<T> FindById<T>( id) where T : ();
int Save<T>(T entity); int Update<T>(T entity); int Remove<T>(T entity); int Remove<>( id) where : (); } }
下面先实现比较简单的查询方法,代码1-2:
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Orm.CustomAttributes; using System.Data.SqlClient; using System.Collections; using System.Data; using System.Orm.DBUtility; using System.Orm.Common; namespace System.Orm.EntityManager { public class : { //......实现EntityManager接口... } }
下面是PropertyImpl 类中FindById方法的代码1-3:
通过主键ID查询数据 public <T> FindById<T>(object id) : new() { <T> listArr = new <T>();
type = ().GetType();
[] properties = .GetProperties(type);
tableInfo = .GetTableInfo(type, .SELECT);
String strSql = .GetFindByIdSql(tableInfo);
[] parms = .CreateDbParameters(1); parms[0].ParameterName = tableInfo.Id.Key; parms[0].Value = id; sdr = null; try {
sdr = .ExecuteReader(.ConnectionString, .Text, strSql, parms);
while (sdr.Read())
{
entity = new (); foreach ( property in properties) {
name = tableInfo.PropToColumn[property.Name].ToString();
.SetPropertyValue(entity, property, sdr[name]); }
listArr.Add(entity); } } catch ( ex) { throw ex; } finally { if (sdr != null) sdr.Close(); } return listArr; }
1-3中第一行代码:TableInfo tableInfo = DbEntityUtils.GetTableInfo(entity,DbOperateType.SELECT);
将实体对象和操作类型传入DbEntityUtils.GetTableInfo方法中,下面是GetTableInfo代码1-4:
public static GetTableInfo(object entity, dbOpType) {
bool breakForeach = false;
string strPrimaryKey = string.Empty;
type = entity.GetType();
tableInfo = new ();
tableInfo.TableName = GetTableName(type);
[] properties = .GetProperties(type); foreach ( property in properties) { object propvalue = null; string columnName = string.Empty; string propName = columnName = property.Name;
if(dbOpType != .SELECT)
propvalue = .GetPropertyValue(entity, property);
object[] propertyAttrs = property.GetCustomAttributes(false); for (int i = 0; i < propertyAttrs.Length; i++) { object propertyAttr = propertyAttrs[i];
if (.IsCaseColumn(propertyAttr, dbOpType)) break;
string tempName = GetColumnName(propertyAttr);
columnName = tempName == string.Empty ? propName : tempName;
if (propertyAttr is ) { if (dbOpType == .INSERT) {
if (.IsNullOrEmpty(propvalue))
{
//获取主键生成方式,存入tableInfo.Strategy属性中
IdAttribute idAttr = propertyAttr as IdAttribute;
tableInfo.Strategy = idAttr.Strategy;
strPrimaryKey = .GetPrimaryKey(propertyAttr); if (!string.IsNullOrEmpty(strPrimaryKey)) propvalue = strPrimaryKey; } }
tableInfo.Id.Key = columnName; tableInfo.Id.Value = propvalue;
tableInfo.PropToColumn.Put(propName, columnName);
breakForeach = true
}
}
if (breakForeach) { breakForeach = false; continue; }
tableInfo.Columns.Put(columnName, propvalue);
tableInfo.PropToColumn.Put(propName, columnName);
}
return tableInfo;
}
在代码1-3中用到了获取实体对象中自定义属性所配置的表名、列名代码分别为1-5:
public static string GetTableName( classType) { string strTableName = string.Empty; string strEntityName = string.Empty; strEntityName = classType.FullName; object classAttr = classType.GetCustomAttributes(false)[0]; if (classAttr is ) { tableAttr = classAttr as ; strTableName = tableAttr.Name; } if (string.IsNullOrEmpty(strTableName)) { throw new ("实体类:" + strEntityName + "的属性配置[Table(name=\"tablename\")]错误或未配置"); } return strTableName; }
上面是获取表名,下面这段代码是获取列名,如下代码1-6:
public static string GetColumnName(object attribute) { string columnName = string.Empty; if (attribute is ) { columnAttr = attribute as ; columnName = columnAttr.Name; } if (attribute is ) { idAttr = attribute as ; columnName = idAttr.Name; } return columnName; }
1-3中第二行代码:String strSql = DbEntityUtils.GetFindByIdSql(tableInfo);
根据已经存入表信息的对象tableInfo来生成SQL语句,代码1-7:
public static GetFindByIdSql( tableInfo) { sbColumns = new (); if (tableInfo.Columns.ContainsKey(tableInfo.Id.Key)) tableInfo.Columns[tableInfo.Id.Key] = tableInfo.Id.Value; else tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value);
foreach (String key in tableInfo.Columns.Keys) { sbColumns.Append(key).Append(","); } sbColumns.Remove(sbColumns.ToString().Length - 1, 1); string strSql = "SELECT {0} FROM {1} WHERE {2} = " + .DbParmChar + "{2}"; strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName, tableInfo.Id.Key);
return strSql;
}
下面是几个工具类代码,ReflectionUtils,根据反射获取或设置对象属性值、DynamicMethodCompiler动态方法编译,可提高反射的性能。
ReflectionUtilsusing System; using System.Collections.Generic; using System.Text; using System.Reflection; namespace System.Orm.Common { public class { public static [] GetProperties( type) { return type.GetProperties(.Public | .Instance); } public static [] GetFields( type) { return type.GetFields(.Public | .Instance); } public static void SetPropertyValue(obj, property, //创建Set委托 setter = .CreateSetHandler(obj.GetType(),property); //先获取该私有成员的数据类型 type = property.PropertyType; //通过数据类型转换 value = .ConvertForType(value, type); //将值设置到对象中 setter(obj, value); } public static GetPropertyValue(obj, property) { //创建Set委托 getter = .CreateGetHandler(obj.GetType(), property); //获取属性值 return getter(obj); } public static void SetFieldValue(obj, field, value) { //创建Set委托 setter = .CreateSetHandler(obj.GetType(), field); //先获取该私有成员的数据类型 type = field.FieldType; //通过数据类型转换 value = .ConvertForType(value, type); //将值设置到对象中 setter(obj, value); } public static GetFieldValue(obj, field) { //创建Set委托 getter = .CreateGetHandler(obj.GetType(), field); //获取字段值 return getter(obj); } } }
DynamicMethodCompiler代码:
DynamicMethodCompilerusing System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Reflection.Emit; namespace System.Orm.Common { //定义GetHandler委托 public delegate object (object source);
//定义SetHandler委托 public delegate void (object source, object value);
//定义InstantiateObjectHandler委托 public delegate object (); public sealed class { // DynamicMethodCompiler private DynamicMethodCompiler() { } // 创建InstantiateObject委托 internal static CreateInstantiateObjectHandler( type) { constructorInfo = type.GetConstructor(.Public | .NonPublic | .Instance, null, new [0], null); if (constructorInfo == null) { throw new (string.Format("The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).", type)); } dynamicMethod = new ("InstantiateObject", .Static | .Public, .Standard, typeof(object), null, type, true); generator = dynamicMethod.GetILGenerator(); generator.Emit(.Newobj, constructorInfo); generator.Emit(.Ret); return ()dynamicMethod.CreateDelegate (typeof()); } // 创建Get委托 internal static CreateGetHandler( type, propertyInfo) { getMethodInfo = propertyInfo.GetGetMethod(true); dynamicGet = CreateGetDynamicMethod(type); getGenerator = dynamicGet.GetILGenerator(); getGenerator.Emit(.Ldarg_0); getGenerator.Emit(.Call, getMethodInfo); BoxIfNeeded(getMethodInfo.ReturnType, getGenerator); getGenerator.Emit(.Ret); return ()dynamicGet.CreateDelegate(typeof()); } // 创建Get委托 internal static CreateGetHandler( type, fieldInfo) { dynamicGet = CreateGetDynamicMethod(type); getGenerator = dynamicGet.GetILGenerator(); getGenerator.Emit(.Ldarg_0); getGenerator.Emit(.Ldfld, fieldInfo); BoxIfNeeded(fieldInfo.FieldType, getGenerator); getGenerator.Emit(.Ret); return ()dynamicGet.CreateDelegate(typeof()); } // 创建Set委托 internal static CreateSetHandler( type, propertyInfo) { setMethodInfo = propertyInfo.GetSetMethod(true); dynamicSet = CreateSetDynamicMethod(type); setGenerator = dynamicSet.GetILGenerator(); setGenerator.Emit(.Ldarg_0); setGenerator.Emit(.Ldarg_1); UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator); setGenerator.Emit(.Call, setMethodInfo); setGenerator.Emit(.Ret); return ()dynamicSet.CreateDelegate(typeof()); } // 创建Set委托 internal static CreateSetHandler( type, fieldInfo) { dynamicSet = CreateSetDynamicMethod(type); setGenerator = dynamicSet.GetILGenerator(); setGenerator.Emit(.Ldarg_0); setGenerator.Emit(.Ldarg_1); UnboxIfNeeded(fieldInfo.FieldType, setGenerator); setGenerator.Emit(.Stfld, fieldInfo); setGenerator.Emit(.Ret); return ()dynamicSet.CreateDelegate(typeof()); } // 创建Get动态方法 private static CreateGetDynamicMethod( type) { return new ("DynamicGet", typeof(object), new [] { typeof(object) }, type, true); } // 创建Set动态方法 private static CreateSetDynamicMethod( type) { return new ("DynamicSet", typeof(void), new [] { typeof(object), typeof(object) }, type, true); } // BoxIfNeeded private static void BoxIfNeeded(type, ILGenerator generator) { if (type.IsValueType) { generator.Emit(.Box, type); } } // UnboxIfNeeded private static void UnboxIfNeeded(Type type, generator) { if (type.IsValueType) { generator.Emit(.Unbox_Any, type); } } } }
TypeUtils代码:
TypeUtilsusing System; using System.Collections.Generic; using System.Text; namespace System.Orm.Common { public class { public static object ConvertForType(object value,type) { switch (type.FullName) { case "System.String": value = value.ToString(); break; case "System.Boolean": value = bool.Parse(value.ToString()); break; case "System.Int16": case "System.Int32": case "System.Int64": value = int.Parse(value.ToString()); break; case "System.Double": value = double.Parse(value.ToString()); break; case "System.Decimal": value = new decimal(double.Parse(value.ToString())); break; } return value; } } }
好了,FindById方法所需的代码和工具类代码都在上面,到此已经完成。