在[基类实现篇]中,私有变量nxSP是真正的实现存储调用的一个类
实现代码:
internal
class
NxStoredProcedure
... {
初始化类#region 初始化类
/**//// <summary>
/// 执行存储过程 .ctor()
/// </summary>
internal NxStoredProcedure()
...{
}
private object GetPrivateFieldValue(object obj, string PrivateFieldName)
...{
//string PrivateFieldName = "_" + pi.Name;;
FieldInfo fi = obj.GetType().GetField(PrivateFieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
//Debug.WriteLine("GetPrivateFieldValue:"+PrivateFieldName);
return fi.GetValue(obj);
}
private void SetPrivateFieldValue(object obj, string PrivateFieldName,object Value)
...{
//string PrivateFieldName = "_" + pi.Name;;
FieldInfo fi = obj.GetType().GetField(PrivateFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
//Debug.WriteLine(PrivateFieldName);
fi.SetValue(obj,Value);
}
private string SPName = string.Empty; //存储过程的名称
private NXExectueReturnAttribute execRtnAttr = null; //存储过程返回结果的属性标识
private ArrayList alAllParams = null; //所有的存储过程上的参数
private ArrayList alOutputParams = null; //输出参数
private string ParamMarker; //参数的前缀 [@,:,?]
private void IniSpData(object InstanceClass)
...{
this.alAllParams = new ArrayList();
this.alOutputParams = new ArrayList();
//Debug.WriteLine("OK");
//本人一个配置类,不同的数据用的参数前缀是不同的,SQLSERVER使用@,Oracle使用: MySql使用?
this.ParamMarker = NxContext.CodmDatas["NxParameterMaker"];
Type type = InstanceClass.GetType();
object[] classAttrs = type.GetCustomAttributes(typeof(NXDataSetAttribute), false);
if (classAttrs.Length == 0) throw new NxException("操作数据库发生错误:你必须使用 [NXDataSet(...)] 来标识类...");
NXDataSetAttribute dsStyle = (NXDataSetAttribute)classAttrs[0];
if(dsStyle.Schema != SchemaFlag.IsStoredProcedure)
throw new NxException("传入的类,未标记成有效的存储过程,请使用 SchemaFlag.IsStoredProcedure 来标识类...");
SPName = dsStyle.ClassName;
取得类在[.ctor()]时的对应属性#region 取得类在[.ctor()]时的对应属性
//取得类在[.ctor()]时的对应属性
//bool IsExistCtorAttributeFlag = false; //类的构造器上是否有一个[NXExectueReturnAttribute]属性
ConstructorInfo[] ciAry = type.GetConstructors();
if(ciAry.Length == 0)throw new Exception(type.Name + " 必须使用类的构造器...");
foreach(ConstructorInfo ci in ciAry)
...{
object[] memAttrs = ci.GetCustomAttributes(typeof(NXExectueReturnAttribute),false);
if (memAttrs == null)continue;
if(memAttrs.Length==0)continue;
execRtnAttr = (NXExectueReturnAttribute)memAttrs[0];
break;
}
if(execRtnAttr == null)throw new Exception("存储的实例类,至少在一个构造器上应用 [NXExectueReturn] 属性标识...");
#endregion
//取得类上的属性
PropertyInfo[] piAry = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo pi in piAry)
...{
object[] memAttrs = pi.GetCustomAttributes(typeof(NXVarAttribute),false);
if (memAttrs == null) continue;
if (memAttrs.Length == 0) continue;
//参数的值,即便是输出参数,也需要设置值
NXVarAttribute varAttr = (NXVarAttribute)memAttrs[0];
varAttr.Value = this.GetPrivateFieldValue(InstanceClass,varAttr.PrivateFieldName);
alAllParams.Add(varAttr);
if(varAttr.Flag == VarIOFlag.IsOutput || varAttr.Flag == VarIOFlag.IsDouble)
...{
alOutputParams.Add(varAttr);
}
}
}
#endregion
真正执行存储过程#region 真正执行存储过程
private object DoExecute(object InstanceClass)
...{
object objValue = null;
//注意,NXCommand此类,是本人继承自IDbCommand来实现通用的命令,其中使用一整套的动态方案来实现不同的命令SQL,ORACLE,MYSQL等
//题外话:使用一个XML做了组件的ORMapping,如果调用SQL,则将 SqlCommand映射到NXCommand上来
NXCommand nxCmd = new NXCommand(this.SPName,NxContext.Source);//NxContext.Source是一个Connection数据库连接对象
nxCmd.CommandType = CommandType.StoredProcedure;
填充所有参数变量信息#region 填充所有参数变量信息
if(this.alAllParams.Count>0)
...{
//填充输入参数变量信息
foreach(object obj in this.alAllParams)
...{
NXVarAttribute varAttr = (NXVarAttribute)obj;
string PrmName = ParamMarker + varAttr.Name;
//if(varAttr.Flag == VarIOFlag.IsInput || varAttr.Flag == VarIOFlag.IsDouble)
nxCmd.Parameters.Add(PrmName, varAttr.Value);
//else
// nxCmd.Parameters.Add(PrmName,0);
if(varAttr.Flag == VarIOFlag.IsInput)
nxCmd.Parameters[PrmName].Direction = ParameterDirection.Input;
else if(varAttr.Flag == VarIOFlag.IsOutput)
nxCmd.Parameters[PrmName].Direction = ParameterDirection.Output;
else if(varAttr.Flag == VarIOFlag.IsDouble)
nxCmd.Parameters[PrmName].Direction = ParameterDirection.InputOutput;
}
}
#endregion
执行存储过程#region 执行存储过程
//开始执行存储过程
if(execRtnAttr.Flag == ReturnFlag.IsDataSet)
...{
DataSet objDs = new DataSet();
//注意,NXDataAdapter此类,是本人继承自DbDataAdapter, IDbDataAdapter, IDataAdapter进行重新实现
using(NXDataAdapter nxDA = new NXDataAdapter(nxCmd))
...{
nxDA.Fill(objDs);
nxDA.Dispose();
}
objValue = objDs;
this.SetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName,objValue);
}
else if(execRtnAttr.Flag == ReturnFlag.IsNonResult)
...{
objValue = nxCmd.ExecuteNonQuery();
}
else if(execRtnAttr.Flag == ReturnFlag.IsValue)
...{
nxCmd.Parameters.Add("ReturnValue",this.GetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName));
nxCmd.Parameters["ReturnValue"].Direction = ParameterDirection.ReturnValue;
nxCmd.ExecuteNonQuery();
objValue = nxCmd.Parameters["ReturnValue"].Value;
if(objValue != System.DBNull.Value)
this.SetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName,objValue);
}
else if(execRtnAttr.Flag == ReturnFlag.IsDouble)
...{
//属性中保存,存储过程的Return语句的返回值
nxCmd.Parameters.Add("ReturnValue",this.GetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName));
nxCmd.Parameters["ReturnValue"].Direction = ParameterDirection.ReturnValue;
//返回DataSet
DataSet objDs = new DataSet();
using(NXDataAdapter nxDA = new NXDataAdapter(nxCmd))
...{
nxDA.Fill(objDs);
nxDA.Dispose();
}
objValue = objDs;
//已经调用[nxDA.Fill],则nxCmd命令已经被执行,
//则[ReturnValue]的参数中已经有返回结果,可能该结果是DBNull.Value
//所以 nxCmd.ExecuteNonQuery(); 注释,只调用一次命令的执行,避免两次调用,给数据库造成压力
object objReturn = nxCmd.Parameters["ReturnValue"].Value;
if(objReturn != System.DBNull.Value)
this.SetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName,objReturn);
}
#endregion
执行完毕后,填充输出参数变量的值,给类上的私有变量#region 执行完毕后,填充输出参数变量的值,给类上的私有变量
if(alOutputParams.Count>0)
...{
//填充输出参数变量的值,给类上的私有变量
foreach(object obj in this.alOutputParams)
...{
NXVarAttribute varAttr = (NXVarAttribute)obj;
string PrmName = ParamMarker + varAttr.Name;
object outValue = nxCmd.Parameters[PrmName].Value;
//如果结果为空,则不需要设置给类上的私有字段
if(outValue == System.DBNull.Value)continue;
if(varAttr.Flag == VarIOFlag.IsOutput || varAttr.Flag == VarIOFlag.IsDouble)
this.SetPrivateFieldValue(InstanceClass,varAttr.PrivateFieldName,outValue);
}
}
#endregion
nxCmd.Dispose();
return objValue;
}
#endregion
公共方法#region 公共方法
/**//// <summary>
/// 执行存储过程
/// </summary>
/// <param name="InstanceClass" >存储过程的实例类</param>
/// <returns>执行结果</returns>
public object Exectue(object InstanceClass)
...{
object obj = null;
this.IniSpData(InstanceClass);
try
...{
obj= this.DoExecute(InstanceClass);
}
catch(Exception ex)
...{
throw ex;
}
return obj;
}
/**//// <summary>
/// 执行存储过程,动态映射成实例的类对象数组
/// </summary>
/// <param name="InstanceClass" >存储过程的实例类</param>
/// <param name="InstanceType">类对象的类型</param>
/// <returns>object[]</returns>
public object[] ExectueToObject(object InstanceClass,Type InstanceType)
...{
this.IniSpData(InstanceClass);
if(execRtnAttr.Flag != ReturnFlag.IsDataSet && execRtnAttr.Flag != ReturnFlag.IsDouble)
throw new NxException("存储过程的返回类型并非是有效的 DataSet对象...");
DataSet ds = null;
try
...{
ds = (DataSet)this.DoExecute(InstanceClass);
}
catch(Exception ex)
...{
throw ex;
}
if(ds==null)return null;
return NxConvert.ToObjectArray(InstanceType,ds);
}
#endregion
}
... {
初始化类#region 初始化类
/**//// <summary>
/// 执行存储过程 .ctor()
/// </summary>
internal NxStoredProcedure()
...{
}
private object GetPrivateFieldValue(object obj, string PrivateFieldName)
...{
//string PrivateFieldName = "_" + pi.Name;;
FieldInfo fi = obj.GetType().GetField(PrivateFieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
//Debug.WriteLine("GetPrivateFieldValue:"+PrivateFieldName);
return fi.GetValue(obj);
}
private void SetPrivateFieldValue(object obj, string PrivateFieldName,object Value)
...{
//string PrivateFieldName = "_" + pi.Name;;
FieldInfo fi = obj.GetType().GetField(PrivateFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
//Debug.WriteLine(PrivateFieldName);
fi.SetValue(obj,Value);
}
private string SPName = string.Empty; //存储过程的名称
private NXExectueReturnAttribute execRtnAttr = null; //存储过程返回结果的属性标识
private ArrayList alAllParams = null; //所有的存储过程上的参数
private ArrayList alOutputParams = null; //输出参数
private string ParamMarker; //参数的前缀 [@,:,?]
private void IniSpData(object InstanceClass)
...{
this.alAllParams = new ArrayList();
this.alOutputParams = new ArrayList();
//Debug.WriteLine("OK");
//本人一个配置类,不同的数据用的参数前缀是不同的,SQLSERVER使用@,Oracle使用: MySql使用?
this.ParamMarker = NxContext.CodmDatas["NxParameterMaker"];
Type type = InstanceClass.GetType();
object[] classAttrs = type.GetCustomAttributes(typeof(NXDataSetAttribute), false);
if (classAttrs.Length == 0) throw new NxException("操作数据库发生错误:你必须使用 [NXDataSet(...)] 来标识类...");
NXDataSetAttribute dsStyle = (NXDataSetAttribute)classAttrs[0];
if(dsStyle.Schema != SchemaFlag.IsStoredProcedure)
throw new NxException("传入的类,未标记成有效的存储过程,请使用 SchemaFlag.IsStoredProcedure 来标识类...");
SPName = dsStyle.ClassName;
取得类在[.ctor()]时的对应属性#region 取得类在[.ctor()]时的对应属性
//取得类在[.ctor()]时的对应属性
//bool IsExistCtorAttributeFlag = false; //类的构造器上是否有一个[NXExectueReturnAttribute]属性
ConstructorInfo[] ciAry = type.GetConstructors();
if(ciAry.Length == 0)throw new Exception(type.Name + " 必须使用类的构造器...");
foreach(ConstructorInfo ci in ciAry)
...{
object[] memAttrs = ci.GetCustomAttributes(typeof(NXExectueReturnAttribute),false);
if (memAttrs == null)continue;
if(memAttrs.Length==0)continue;
execRtnAttr = (NXExectueReturnAttribute)memAttrs[0];
break;
}
if(execRtnAttr == null)throw new Exception("存储的实例类,至少在一个构造器上应用 [NXExectueReturn] 属性标识...");
#endregion
//取得类上的属性
PropertyInfo[] piAry = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo pi in piAry)
...{
object[] memAttrs = pi.GetCustomAttributes(typeof(NXVarAttribute),false);
if (memAttrs == null) continue;
if (memAttrs.Length == 0) continue;
//参数的值,即便是输出参数,也需要设置值
NXVarAttribute varAttr = (NXVarAttribute)memAttrs[0];
varAttr.Value = this.GetPrivateFieldValue(InstanceClass,varAttr.PrivateFieldName);
alAllParams.Add(varAttr);
if(varAttr.Flag == VarIOFlag.IsOutput || varAttr.Flag == VarIOFlag.IsDouble)
...{
alOutputParams.Add(varAttr);
}
}
}
#endregion
真正执行存储过程#region 真正执行存储过程
private object DoExecute(object InstanceClass)
...{
object objValue = null;
//注意,NXCommand此类,是本人继承自IDbCommand来实现通用的命令,其中使用一整套的动态方案来实现不同的命令SQL,ORACLE,MYSQL等
//题外话:使用一个XML做了组件的ORMapping,如果调用SQL,则将 SqlCommand映射到NXCommand上来
NXCommand nxCmd = new NXCommand(this.SPName,NxContext.Source);//NxContext.Source是一个Connection数据库连接对象
nxCmd.CommandType = CommandType.StoredProcedure;
填充所有参数变量信息#region 填充所有参数变量信息
if(this.alAllParams.Count>0)
...{
//填充输入参数变量信息
foreach(object obj in this.alAllParams)
...{
NXVarAttribute varAttr = (NXVarAttribute)obj;
string PrmName = ParamMarker + varAttr.Name;
//if(varAttr.Flag == VarIOFlag.IsInput || varAttr.Flag == VarIOFlag.IsDouble)
nxCmd.Parameters.Add(PrmName, varAttr.Value);
//else
// nxCmd.Parameters.Add(PrmName,0);
if(varAttr.Flag == VarIOFlag.IsInput)
nxCmd.Parameters[PrmName].Direction = ParameterDirection.Input;
else if(varAttr.Flag == VarIOFlag.IsOutput)
nxCmd.Parameters[PrmName].Direction = ParameterDirection.Output;
else if(varAttr.Flag == VarIOFlag.IsDouble)
nxCmd.Parameters[PrmName].Direction = ParameterDirection.InputOutput;
}
}
#endregion
执行存储过程#region 执行存储过程
//开始执行存储过程
if(execRtnAttr.Flag == ReturnFlag.IsDataSet)
...{
DataSet objDs = new DataSet();
//注意,NXDataAdapter此类,是本人继承自DbDataAdapter, IDbDataAdapter, IDataAdapter进行重新实现
using(NXDataAdapter nxDA = new NXDataAdapter(nxCmd))
...{
nxDA.Fill(objDs);
nxDA.Dispose();
}
objValue = objDs;
this.SetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName,objValue);
}
else if(execRtnAttr.Flag == ReturnFlag.IsNonResult)
...{
objValue = nxCmd.ExecuteNonQuery();
}
else if(execRtnAttr.Flag == ReturnFlag.IsValue)
...{
nxCmd.Parameters.Add("ReturnValue",this.GetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName));
nxCmd.Parameters["ReturnValue"].Direction = ParameterDirection.ReturnValue;
nxCmd.ExecuteNonQuery();
objValue = nxCmd.Parameters["ReturnValue"].Value;
if(objValue != System.DBNull.Value)
this.SetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName,objValue);
}
else if(execRtnAttr.Flag == ReturnFlag.IsDouble)
...{
//属性中保存,存储过程的Return语句的返回值
nxCmd.Parameters.Add("ReturnValue",this.GetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName));
nxCmd.Parameters["ReturnValue"].Direction = ParameterDirection.ReturnValue;
//返回DataSet
DataSet objDs = new DataSet();
using(NXDataAdapter nxDA = new NXDataAdapter(nxCmd))
...{
nxDA.Fill(objDs);
nxDA.Dispose();
}
objValue = objDs;
//已经调用[nxDA.Fill],则nxCmd命令已经被执行,
//则[ReturnValue]的参数中已经有返回结果,可能该结果是DBNull.Value
//所以 nxCmd.ExecuteNonQuery(); 注释,只调用一次命令的执行,避免两次调用,给数据库造成压力
object objReturn = nxCmd.Parameters["ReturnValue"].Value;
if(objReturn != System.DBNull.Value)
this.SetPrivateFieldValue(InstanceClass,execRtnAttr.PrivateFieldName,objReturn);
}
#endregion
执行完毕后,填充输出参数变量的值,给类上的私有变量#region 执行完毕后,填充输出参数变量的值,给类上的私有变量
if(alOutputParams.Count>0)
...{
//填充输出参数变量的值,给类上的私有变量
foreach(object obj in this.alOutputParams)
...{
NXVarAttribute varAttr = (NXVarAttribute)obj;
string PrmName = ParamMarker + varAttr.Name;
object outValue = nxCmd.Parameters[PrmName].Value;
//如果结果为空,则不需要设置给类上的私有字段
if(outValue == System.DBNull.Value)continue;
if(varAttr.Flag == VarIOFlag.IsOutput || varAttr.Flag == VarIOFlag.IsDouble)
this.SetPrivateFieldValue(InstanceClass,varAttr.PrivateFieldName,outValue);
}
}
#endregion
nxCmd.Dispose();
return objValue;
}
#endregion
公共方法#region 公共方法
/**//// <summary>
/// 执行存储过程
/// </summary>
/// <param name="InstanceClass" >存储过程的实例类</param>
/// <returns>执行结果</returns>
public object Exectue(object InstanceClass)
...{
object obj = null;
this.IniSpData(InstanceClass);
try
...{
obj= this.DoExecute(InstanceClass);
}
catch(Exception ex)
...{
throw ex;
}
return obj;
}
/**//// <summary>
/// 执行存储过程,动态映射成实例的类对象数组
/// </summary>
/// <param name="InstanceClass" >存储过程的实例类</param>
/// <param name="InstanceType">类对象的类型</param>
/// <returns>object[]</returns>
public object[] ExectueToObject(object InstanceClass,Type InstanceType)
...{
this.IniSpData(InstanceClass);
if(execRtnAttr.Flag != ReturnFlag.IsDataSet && execRtnAttr.Flag != ReturnFlag.IsDouble)
throw new NxException("存储过程的返回类型并非是有效的 DataSet对象...");
DataSet ds = null;
try
...{
ds = (DataSet)this.DoExecute(InstanceClass);
}
catch(Exception ex)
...{
throw ex;
}
if(ds==null)return null;
return NxConvert.ToObjectArray(InstanceType,ds);
}
#endregion
}
此类,本人在实现时,实际上专写了一个接口,是通过此接口完成的,但此类现在是完成可以正常工作的
其中的NXCommand,NXDataAdapter,是专为连接各个不同的数据而写,你可以替换成SQLCommand等
如对NXCommand,NXDataAdapter等类有兴趣,可以一起研究讨论!
如需转载,请表明出处
anthor:zerodj@163.com/javasuki@hotmail.com