利用动态代理实现通用存储过程的调用

   很久没有更新了,哈哈,最近太懒惰了,业余时间,写了一个关于存储过程的调用的东东,部分思想来自于Lostinet大大写的 用 System.Reflection.Emit 自动实现调用存储过程的接口,他的实现是用Emit,我改用动态代理,其实内部都用到Emit

   通常情况下我们利用ADO.NET调用存储过程往往要写上好多代码,特别存储过程是参数很多的话很容易出错,而且很繁琐,看看下面这段调用存储过程的代码:
ContractedBlock.gif ExpandedBlockStart.gif
  public static void au_UpdateU_jbxxi(
                    
int xs_id, 
                    
object xj_bhao, 
                    
string xs_xming, 
                    
string xbie, 
                    System.DateTime sri, 
                    
int bj_ID, 
                    
string mzhu, 
                    
object rxxxi, 
                    
object rxcji, 
                    
object tcahao, 
                    
object tpian, 
                    
string jtdhua, 
                    
object paytel, 
                    
object ybian, 
                    
string dzhi, 
                    
object qtlxi, 
                    
object xsjkuang, 
                    
object fCard, 
                    
object stuID, 
                    
object entrYear, 
                    
object schoolingLength, 
                    
object fSyncState)
ExpandedBlockStart.gifContractedBlock.gif        
{
            
// 创建一个连接
            System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(EnterpriseObjects.EnterpriseApplication.Application.ConnectionString);
            connection.Open();
            
// 创建一个命令
            System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("au_UpdateU_jbxxi", connection);
            command.CommandType 
= System.Data.CommandType.StoredProcedure;
            
// 参数
            System.Data.SqlClient.SqlParameter xs_idParam = command.Parameters.Add("@xs_id", System.Data.SqlDbType.Int);
            xs_idParam.Value 
= xs_id;
            System.Data.SqlClient.SqlParameter xj_bhaoParam 
= command.Parameters.Add("@xj_bhao", System.Data.SqlDbType.VarChar, 30);
            
if ((xj_bhao == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                xj_bhaoParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                xj_bhaoParam.Value 
= xj_bhao;
            }

            System.Data.SqlClient.SqlParameter xs_xmingParam 
= command.Parameters.Add("@xs_xming", System.Data.SqlDbType.VarChar, 30);
            xs_xmingParam.Value 
= xs_xming;
            System.Data.SqlClient.SqlParameter xbieParam 
= command.Parameters.Add("@xbie", System.Data.SqlDbType.VarChar, 2);
            xbieParam.Value 
= xbie;
            System.Data.SqlClient.SqlParameter sriParam 
= command.Parameters.Add("@sri", System.Data.SqlDbType.DateTime);
            sriParam.Value 
= sri;
            System.Data.SqlClient.SqlParameter bj_IDParam 
= command.Parameters.Add("@bj_ID", System.Data.SqlDbType.Int);
            bj_IDParam.Value 
= bj_ID;
            System.Data.SqlClient.SqlParameter mzhuParam 
= command.Parameters.Add("@mzhu", System.Data.SqlDbType.VarChar, 20);
            mzhuParam.Value 
= mzhu;
            System.Data.SqlClient.SqlParameter rxxxiParam 
= command.Parameters.Add("@rxxxi", System.Data.SqlDbType.VarChar, 1000);
            
if ((rxxxi == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                rxxxiParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                rxxxiParam.Value 
= rxxxi;
            }

            System.Data.SqlClient.SqlParameter rxcjiParam 
= command.Parameters.Add("@rxcji", System.Data.SqlDbType.Int);
            
if ((rxcji == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                rxcjiParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                rxcjiParam.Value 
= rxcji;
            }

            System.Data.SqlClient.SqlParameter tcahaoParam 
= command.Parameters.Add("@tcahao", System.Data.SqlDbType.VarChar, 300);
            
if ((tcahao == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                tcahaoParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                tcahaoParam.Value 
= tcahao;
            }

            System.Data.SqlClient.SqlParameter tpianParam 
= command.Parameters.Add("@tpian", System.Data.SqlDbType.VarChar, 50);
            
if ((tpian == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                tpianParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                tpianParam.Value 
= tpian;
            }

            System.Data.SqlClient.SqlParameter jtdhuaParam 
= command.Parameters.Add("@jtdhua", System.Data.SqlDbType.VarChar, 50);
            jtdhuaParam.Value 
= jtdhua;
            System.Data.SqlClient.SqlParameter paytelParam 
= command.Parameters.Add("@paytel", System.Data.SqlDbType.VarChar, 50);
            
if ((paytel == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                paytelParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                paytelParam.Value 
= paytel;
            }

            System.Data.SqlClient.SqlParameter ybianParam 
= command.Parameters.Add("@ybian", System.Data.SqlDbType.VarChar, 6);
            
if ((ybian == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                ybianParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                ybianParam.Value 
= ybian;
            }

            System.Data.SqlClient.SqlParameter dzhiParam 
= command.Parameters.Add("@dzhi", System.Data.SqlDbType.VarChar, 100);
            dzhiParam.Value 
= dzhi;
            System.Data.SqlClient.SqlParameter qtlxiParam 
= command.Parameters.Add("@qtlxi", System.Data.SqlDbType.VarChar, 100);
            
if ((qtlxi == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                qtlxiParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                qtlxiParam.Value 
= qtlxi;
            }

            System.Data.SqlClient.SqlParameter xsjkuangParam 
= command.Parameters.Add("@xsjkuang", System.Data.SqlDbType.VarChar, 2000);
            
if ((xsjkuang == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                xsjkuangParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                xsjkuangParam.Value 
= xsjkuang;
            }

            System.Data.SqlClient.SqlParameter fCardParam 
= command.Parameters.Add("@fCard", System.Data.SqlDbType.VarChar, 20);
            
if ((fCard == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                fCardParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                fCardParam.Value 
= fCard;
            }

            System.Data.SqlClient.SqlParameter stuIDParam 
= command.Parameters.Add("@stuID", System.Data.SqlDbType.Char, 6);
            
if ((stuID == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                stuIDParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                stuIDParam.Value 
= stuID;
            }

            System.Data.SqlClient.SqlParameter entrYearParam 
= command.Parameters.Add("@entrYear", System.Data.SqlDbType.VarChar, 4);
            
if ((entrYear == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                entrYearParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                entrYearParam.Value 
= entrYear;
            }

            System.Data.SqlClient.SqlParameter schoolingLengthParam 
= command.Parameters.Add("@schoolingLength", System.Data.SqlDbType.Int);
            
if ((schoolingLength == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                schoolingLengthParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                schoolingLengthParam.Value 
= schoolingLength;
            }

            System.Data.SqlClient.SqlParameter fSyncStateParam 
= command.Parameters.Add("@fSyncState", System.Data.SqlDbType.VarChar, 50);
            
if ((fSyncState == null))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                fSyncStateParam.Value 
= System.DBNull.Value;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                fSyncStateParam.Value 
= fSyncState;
            }

            
// 执行
            command.ExecuteNonQuery();
            
// 清除
            command.Dispose();
            connection.Close();
        }

        

      晕,居然这么多,不知道你觉得烦不烦,反正我是很讨厌,很反感了。

      其实利用动态代理,可以解决很多问题,现在先假设我们调用的模式:
  1.定义调用的接口,方法名对应到要调用的存储过程名,参数也与之对应(注:我用的实例数据库是NorthWind):
     public   interface  ISproces
ExpandedBlockStart.gifContractedBlock.gif    
{
        System.Data.DataSet CustOrderHist(
string CustomerID);
        DataSet CustOrdersDetail(
int OrderID);
    
        
//如果储存过程名字和方法名字不同,应该用SpCustomNameAttribute来进行说明
        [SpCustomNameAttribute("Employee Sales By Country")]
        DataSet EmployeeSalesByCountry(DateTime Beginning_Date,DateTime Ending_Date);
    }
2.利用Castle的DynamicProxy拦截对接口ISproces的调用,并写自己的拦截类SprocInterceptor,
如果不清楚DynamicProxy请参见园子里的一些优秀的文章: DynamicProxy(动态代理)技术剖析(1)  DynamicProxy(动态代理)技术剖析(2)
ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
    
/// 该类负责拦截接口中方法的执行,并调用对应的存储过程
    
/// </summary>

     public   class  SprocInterceptor:StandardInterceptor
ExpandedBlockStart.gifContractedBlock.gif    
{
        
public SqlConnection connection;

        
public SprocInterceptor()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
        }


        
public override object Intercept(IInvocation invocation, params object[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            MethodInfo method
=invocation.Method;
            connection.Open();
            
string methodName="";
            
object returnObj=null;
            
if (invocation.Method.IsDefined(typeof(SpCustomNameAttribute),true))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                methodName 
=SpCustomNameAttribute.GetSPName(method);
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                methodName
=method.Name;
            }

            SqlCommand command 
= new SqlCommand(methodName, connection);
            command.CommandType 
= System.Data.CommandType.StoredProcedure;
            ParameterInfo[] paramInfos
=method.GetParameters();
            
int paramlength=paramInfos.Length;
            
for(int i=0;i<paramlength;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Type type
=paramInfos[i].ParameterType;
                SqlDbType sqlType
=ConvertSqlType(type);
                SqlParameter PageIndexParam 
= command.Parameters.Add("@"+paramInfos[i].Name, sqlType);
                PageIndexParam.Value 
= args[i];
            }


            
if(method.ReturnType==typeof(void))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
// 执行
                command.ExecuteNonQuery();
            }

            
else if(method.ReturnType==typeof(DataSet))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
// 取出数据集
                SqlDataAdapter adapter = new SqlDataAdapter(command);
                DataSet dataset 
= new DataSet();
                adapter.Fill(dataset);
                adapter.Dispose();
                returnObj
=dataset;
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                SqlParameter returnValueParam 
= command.Parameters.Add("@returnValueParam",ConvertSqlType(method.ReturnType));
                returnValueParam.Direction 
= System.Data.ParameterDirection.ReturnValue;
                
// 执行
                command.ExecuteNonQuery();
                returnObj
=Convert.ChangeType(returnValueParam.Value,method.ReturnType);
            }

            
// 清除
            command.Dispose();
            connection.Close();
            
return returnObj;
        
        }

}


      该类继承自StandardInterceptor,并重写了Intercept方法实现对调用的方法的拦截,invocation得到调用的方法名,返回值,参数名,参数的类型而params object[] args参数对应的数据,得到这些数据后,我们便可以很轻松的构造对存储过程的ADO.NET调用的代码了,同时区分处理返回值和void的情况。
     值得注意的是:SqlParameter param = command.Parameters.Add("@"+paramInfos[i].Name, sqlType);这个sqlType是SQL server对应的数据类型的枚举,所以这里需要一个映射,使.net的Type转换到SqlDbType,很简单:

 1
 2 ExpandedBlockStart.gifContractedBlock.gif         /**/ /// <summary>
 3        /// 转化类型到SQL server对应的数据类型
 4        /// </summary>
 5        /// <param name="type"></param>
 6        /// <returns></returns>

 7          public   static  SqlDbType ConvertSqlType(Type type) 
 8 ExpandedBlockStart.gifContractedBlock.gif        
 9            if (type.FullName.ToLower() == "system.int64"
10ExpandedSubBlockStart.gifContractedSubBlock.gif            
11                return SqlDbType.BigInt; 
12            }
 
13            else if (type.FullName.ToLower() == "system.boolean"
14ExpandedSubBlockStart.gifContractedSubBlock.gif            
15                return SqlDbType.Bit; 
16            }
 
17            else if (type.FullName.ToLower() == "system.datetime"
18ExpandedSubBlockStart.gifContractedSubBlock.gif            
19                return SqlDbType.DateTime; 
20            }
 
21            else if (type.FullName.ToLower() == "system.decimal"
22ExpandedSubBlockStart.gifContractedSubBlock.gif            
23                return SqlDbType.Decimal; 
24            }
 
25            else if (type.FullName.ToLower() == "system.double"
26ExpandedSubBlockStart.gifContractedSubBlock.gif            
27                return SqlDbType.Float; 
28            }
 
29            else if (type.FullName.ToLower() == "system.int32"
30ExpandedSubBlockStart.gifContractedSubBlock.gif            
31                return SqlDbType.Int; 
32            }
 
33            else if (type.FullName.ToLower() == "system.single"
34ExpandedSubBlockStart.gifContractedSubBlock.gif            
35                return SqlDbType.Real; 
36            }
 
37            else if (type.FullName.ToLower() == "system.int16"
38ExpandedSubBlockStart.gifContractedSubBlock.gif            
39                return SqlDbType.SmallInt; 
40            }
 
41            else if (type.FullName.ToLower() == "system.byte"
42ExpandedSubBlockStart.gifContractedSubBlock.gif            
43                return SqlDbType.TinyInt; 
44            }
 
45            else if (type.FullName.ToLower() == "system.guid"
46ExpandedSubBlockStart.gifContractedSubBlock.gif            
47                return SqlDbType.UniqueIdentifier; 
48            }
 
49            else if (type.FullName.ToLower() == "system.byte()"
50ExpandedSubBlockStart.gifContractedSubBlock.gif            
51                return SqlDbType.VarBinary; 
52            }
 
53            else if (type.FullName.ToLower() == "system.string"
54ExpandedSubBlockStart.gifContractedSubBlock.gif            
55                return SqlDbType.VarChar; 
56            }
 
57            else if (type.FullName.ToLower() == "system.object"
58ExpandedSubBlockStart.gifContractedSubBlock.gif            
59                return SqlDbType.Variant; 
60            }
 
61            else 
62ExpandedSubBlockStart.gifContractedSubBlock.gif            
63                throw new ArgumentOutOfRangeException(); 
64            }
 
65        }

3.需要给定义了存储过程方法的接口创建代理,使得拦截器去拦截其中的方法:

ExpandedBlockStart.gif ContractedBlock.gif      /**/ /// <summary>
    
/// InvokeSP 的摘要说明。
    
/// </summary>

     public   class  SpProxy
ExpandedBlockStart.gifContractedBlock.gif    
{
        
//public SqlConnection connection;
        public SpProxy()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
        }


        
public static object CreatSpObject(Type inerfaceType,SqlConnection connection)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            ProxyGenerator _generator 
= new ProxyGenerator(); 
            GeneratorContext context 
= new GeneratorContext(); 
            SprocInterceptor interceptor 
= new SprocInterceptor();
            interceptor.connection
=connection;
            
object proxy = _generator.CreateCustomProxy(inerfaceType, interceptor,new noUse(), context);
            
return proxy;
        }


        
private class noUse
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
        }


    }

4.如何调用呢??肯定有很多朋友都会问的。

         private   void  button2_Click( object  sender, System.EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
{
            System.Data.SqlClient.SqlConnection connection
=new System.Data.SqlClient.SqlConnection("Initial Catalog=Northwind;Data Source=(local);Packet Size=4096;user id=sa;password=sa");
            
object proxy=SpProxy.CreatSpObject(typeof(ISproces),connection);
            ISproces sp
=proxy as ISproces;
            DataSet ds
=sp.CustOrdersDetail(10249);
            dataGrid1.DataSource
=ds.Tables[0];
        }

这样就可以对ISporces中定义的方法映射到对应名称的存储过程上去,实现调用。

示例代码下载

 

转载于:https://www.cnblogs.com/jintan/archive/2007/04/28/731217.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值