您的位置:首页 > 其它

自己动手写ORM框架(六):实现查询功能FindById方法

2010-07-03 11:31 761 查看
通过配置实体与表的关系映射后,就可以实现对表的操作了,接下来实现简单对象的新增功能。下面代码1-1是定义的操作数据对象方法的接口:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Data;
usingSystem.Data.SqlClient;

namespaceSystem.Orm.EntityManager
{
publicinterfaceEntityManager
{
//事物
IDbTransactionTransaction{get;set;}
//查询表所有数据
List<T>FindAll<T>()whereT:new();
//自定义SQL查询
List<T>FindBySql<T>(stringstrSql)whereT:new();
//通过主键ID查询
List<T>FindById<T>(objectid)whereT:new();
//新增
intSave<T>(Tentity);

//修改
intUpdate<T>(Tentity);

//删除
intRemove<T>(Tentity);

//根据ID删除数据
intRemove<T>(objectid)whereT:new();
}
}


下面先实现比较简单的查询方法,代码1-2:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Reflection;
usingSystem.Orm.CustomAttributes;
usingSystem.Data.SqlClient;
usingSystem.Collections;
usingSystem.Data;
usingSystem.Orm.DBUtility;
usingSystem.Orm.Common;

namespaceSystem.Orm.EntityManager
{
publicclassEntityManagerImpl:EntityManager
{
//......实现EntityManager接口...
}
}

下面是PropertyImpl类中FindById方法的代码1-3:

#region通过主键ID查询数据
publicList<T>FindById<T>(objectid)whereT:new()
{
List<T>listArr=newList<T>();
//获取泛型T对象的类型
Typetype=newT().GetType();
//获取属性信息数组
PropertyInfo[]properties=ReflectionUtils.GetProperties(type);
//获取实体对象中的表名、列名、列值信息并存于TableInfo对象中
TableInfotableInfo=DbEntityUtils.GetTableInfo(type,DbOperateType.SELECT);
//生成查询SQL语句
StringstrSql=DbEntityUtils.GetFindByIdSql(tableInfo);

//创建参数数组,并将主键ID键值存入参数数组中
IDbDataParameter[]parms=DbFactory.CreateDbParameters(1);
parms[0].ParameterName=tableInfo.Id.Key;
parms[0].Value=id;

IDataReadersdr=null;
try
{
sdr=AdoHelper.ExecuteReader(AdoHelper.ConnectionString,CommandType.Text,strSql,parms);
while(sdr.Read())
{
//创建实体类对象
Tentity=newT();
foreach(PropertyInfopropertyinproperties)
{
//通过实体类属性名称获取Column自定义属性配置的映射列名
sttringname=tableInfo.PropToColumn[property.Name].ToString();
//通过获取的列名从dataReader中检索值,并赋给实体对象属性
ReflectionUtils.SetPropertyValue(entity,property,sdr[name]);
}

//将实体对象添加到List中
listArr.Add(entity);
}
}
catch(Exceptionex)
{
throwex;
}
finally
{
if(sdr!=null)sdr.Close();
}

returnlistArr;
}
#endregion

1-3中第一行代码:TableInfotableInfo=DbEntityUtils.GetTableInfo(entity,DbOperateType.SELECT);

将实体对象和操作类型传入DbEntityUtils.GetTableInfo方法中,下面是GetTableInfo代码1-4:

publicstaticTableInfoGetTableInfo(objectentity,DbOperateTypedbOpType)
{
boolbreakForeach=false;//是否跳出forach循环
stringstrPrimaryKey=string.Empty;//主键变量
Typetype=entity.GetType();//获取实体对象类型
TableInfotableInfo=newTableInfo();//存储表信息的对象

tableInfo.TableName=GetTableName(type);//获取表名
//获取属性信息数组
PropertyInfo[]properties=ReflectionUtils.GetProperties(type);
foreach(PropertyInfopropertyinproperties)
{
objectpropvalue=null;//属性值
stringcolumnName=string.Empty;//列名(数据库表结构)
stringpropName=columnName=property.Name;//属性名称
//如果不是做查询操作,获取属性值
if(dbOpType!=DbOperateType.SELECT)
propvalue=ReflectionUtils.GetPropertyValue(entity,property);
//获取实体对象属性自定义属性数组(如Column、Id、Table)
object[]propertyAttrs=property.GetCustomAttributes(false);
for(inti=0;i<propertyAttrs.Length;i++)
{
objectpropertyAttr=propertyAttrs[i];
//判断是否忽略列,即不插入或更新到数据库中(IsInsert=false、IsUpdate=false)
if(DbEntityUtils.IsCaseColumn(propertyAttr,dbOpType))
break;

//获取Column自定义属性中配置的Name值(表的列名)
stringtempName=GetColumnName(propertyAttr);
//如果属性上未配置Column或Column上未配置Name,则取属性名称作为列名
columnName=tempName==string.Empty?propName:tempName;
//判断自定义属性是否为Id
if(propertyAttrisIdAttribute)
{
if(dbOpType==DbOperateType.INSERT)
{
if(CommonUtils.IsNullOrEmpty(propvalue))
{

//获取主键生成方式,存入tableInfo.Strategy属性中
IdAttributeidAttr=propertyAttrasIdAttribute;
tableInfo.Strategy=idAttr.Strategy;
//如果是插入操作,且主键ID值为空,则根据主键生成策略生成主键值,
//默认生成策略为自动增长,这种情况不处理,有数据库来处理
strPrimaryKey=DbEntityUtils.GetPrimaryKey(propertyAttr);
if(!string.IsNullOrEmpty(strPrimaryKey))
propvalue=strPrimaryKey;
}
}
//将列名,属性值加入到tableInfo的Id对象中
tableInfo.Id.Key=columnName;
tableInfo.Id.Value=propvalue;
//将列名、属性名作对应关系,保存于tableInfo.PropToColumn中,以作后用
tableInfo.PropToColumn.Put(propName,columnName);
breakForeach=true;//如果为Id,则跳出Foreach循环
}
}
//如果breakForeach=true跳出进入下一次循环continue
if(breakForeach){breakForeach=false;continue;}
//将列名、属性值加入到tableInfo.Columns中
tableInfo.Columns.Put(columnName,propvalue);
//将属性名、列名作对应关系,以作后用
tableInfo.PropToColumn.Put(propName,columnName);
}

returntableInfo;
}

在代码1-3中用到了获取实体对象中自定义属性所配置的表名、列名代码分别为1-5:

publicstaticstringGetTableName(TypeclassType)
{
stringstrTableName=string.Empty;
stringstrEntityName=string.Empty;

strEntityName=classType.FullName;

objectclassAttr=classType.GetCustomAttributes(false)[0];
if(classAttrisTableAttribute)
{
TableAttributetableAttr=classAttrasTableAttribute;
strTableName=tableAttr.Name;
}
if(string.IsNullOrEmpty(strTableName))
{
thrownewException("实体类:"+strEntityName+"的属性配置[Table(name=\"tablename\")]错误或未配置");
}

returnstrTableName;
}

上面是获取表名,下面这段代码是获取列名,如下代码1-6:

publicstaticstringGetColumnName(objectattribute)
{
stringcolumnName=string.Empty;
if(attributeisColumnAttribute)
{
ColumnAttributecolumnAttr=attributeasColumnAttribute;
columnName=columnAttr.Name;
}
if(attributeisIdAttribute)
{
IdAttributeidAttr=attributeasIdAttribute;
columnName=idAttr.Name;
}

returncolumnName;
}


1-3中第二行代码:StringstrSql=DbEntityUtils.GetFindByIdSql(tableInfo);
根据已经存入表信息的对象tableInfo来生成SQL语句,代码1-7:

publicstaticstringGetFindByIdSql(TableInfotableInfo)
{
StringBuildersbColumns=newStringBuilder();

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);

//根据Columns中的keys生成例如"studentid,studentno,name,sex..”字符串
foreach(StringkeyintableInfo.Columns.Keys)
{
sbColumns.Append(key).Append(",");
}

sbColumns.Remove(sbColumns.ToString().Length-1,1);

stringstrSql="SELECT{0}FROM{1}WHERE{2}="+AdoHelper.DbParmChar+"{2}";
strSql=string.Format(strSql,sbColumns.ToString(),tableInfo.TableName,tableInfo.Id.Key);

//得到如strSql=”selectstudentid,studentno,name,sex..fromstudent
wherestudentid=@studentid”;(oracle数据库参数前用:,sqlserver用@)
returnstrSql;
}


下面是几个工具类代码,ReflectionUtils,根据反射获取或设置对象属性值、DynamicMethodCompiler动态方法编译,可提高反射的性能。

TypeUtilsusingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;

namespaceSystem.Orm.Common
{
publicclassTypeUtils
{
publicstaticobjectConvertForType(objectvalue,Typetype)
{
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=newdecimal(double.Parse(value.ToString()));
break;
}

returnvalue;
}
}
}


好了,FindById方法所需的代码和工具类代码都在上面,到此已经完成。

Technorati标签:ORM
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: