zoukankan      html  css  js  c++  java
  • quartz.net定时任务框架详解

    C#做定时任务:一是Timer;而是Quartz.net;本文就学习一下Quartz.net框架

    Quartz.net非常的灵活,开发人员能用很少的代码就能完成“每隔一小时执行”、“每天2点执行”、“每月27日的下午执行8次”等各种定时任务。它实现了作业job和触发器trigger之间多对多的关系,还能把多个作业与不同的触发器关联。

    开发步骤:

    1、添加Quartz.dll引用

      第三方框架从“管理NuGet程序包”中搜索并添加,如果高版本安装不成功请试试低版本。我使用的”.NETFramework,Version=v4.5“,无法安装“Quartz.net 3.0.5”版本,但可以安装"2.4.1"。安装完之后会自动添加如下图所示的另外两个引用。

     2、{我建得是WindowsFrrm项目)修改Form1程序代码

    using Quartz;
    using Quartz.Impl;
    using System;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication_1709
    {
        public partial class Form1 : Form
        {
            
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                CodeMethod();//通过代码的方式调用
                //ConfigMethod();
            }
            public static log4net.ILog log = log4net.LogManager.GetLogger("LogLogger");
    
            /// <summary>
            /// 通过代码的方式调用
            /// </summary>
            private static void CodeMethod()
            {
                
                try
                {
                    log.Info("-----------------" + DateTime.Now.ToString() + " Initializing ----------------------");
                    //1.首先创建一个作业调度池
                    ISchedulerFactory scheduler = new StdSchedulerFactory();
                    IScheduler sched = scheduler.GetScheduler();
                    log.Info("-----------------" + DateTime.Now.ToString() + " Initialization Complete -----------");
                    log.Info("-----------------" + DateTime.Now.ToString() + " Scheduling Job  -------------------");
                    //2.创建一个具体的作业
                    IJobDetail job = JobBuilder.Create<PostRawMaterialDistributionPlan>().Build();
                    //3.创建并配置一个触发器
                    #region 每隔5秒执行一次Execute方法,无休止
                    ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(5).WithRepeatCount(int.MaxValue)).Build();
                    #endregion
    
                    #region 程序每5秒执行一次,一共执行50次,开始执行时间设定在当前时间,结束时间设定在1小时候,不管50次有没有执行完,1小时候程序都不在继续执行
                    //DateTimeOffset startTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddSeconds(1), 2);
                    //DateTimeOffset endTime = DateBuilder.NextGivenSecondDate(DateTime.Now.AddMinutes(5), 5);
                    //ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().StartAt(startTime).EndAt(endTime).WithSimpleSchedule(x => x.WithIntervalInSeconds(5).WithRepeatCount(50)).Build();
                    #endregion
    
                    #region 实现各种时间纬度的调用(使用cron-like):在每小时的第10、20、30分钟,每分钟的第11、27秒执行一次
                    //ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create().StartAt(startTime).EndAt(endTime).WithCronSchedule("11,27 0,2,58 * * * ? ").Build();
                    #endregion
    
                    //4.加入作业调度池中
                    sched.ScheduleJob(job, trigger);
                    //5.开始执行
                    sched.Start();
                    log.Info("-----------------" + DateTime.Now.ToString() + " Started Scheduler -----------------");
                    Thread.Sleep(TimeSpan.FromSeconds(65));//第一个线程执行之后休息65秒,第二个线程开始执行,等第十个线程执行完后刚刚好就又该第一个线程执行了,因为定时器设置的是每5秒执行一次
                    log.Info("-----------------" + DateTime.Now.ToString() + " Shutting Down ---------------------");
                    sched.Shutdown(true);
                    log.Info("-----------------" + DateTime.Now.ToString() + " Shutdown Complete -----------------");
                }
                catch (Exception ec)
                {
                    log.Error("-----------------" + DateTime.Now.ToString() + "[Error Occurred]", ec);
                }
    
                
            }
    
    
            /// <summary>
            /// 通过配置文件的方式调用 static
            /// </summary>
            private static void ConfigMethod()
            {
                try
                {
                    log.Info("-----------------" + DateTime.Now.ToString() + " Initializing ----------------------");
                    //工厂
                    ISchedulerFactory factory = new StdSchedulerFactory();
                    //启动
                    IScheduler scheduler = factory.GetScheduler();
    
                    scheduler.Start();
                    log.Info("-----------------" + DateTime.Now.ToString() + " Started Scheduler -----------------");
                    PostRawMaterialDistributionPlan job = new PostRawMaterialDistributionPlan();
                    job.Execute(null);
                    Thread.Sleep(TimeSpan.FromSeconds(65));//第一个线程执行之后休息65秒,第二个线程开始执行,等第十个线程执行完后刚刚好就又该第一个线程执行了,因为定时器设置的是每5秒执行一次
                    log.Info("-----------------" + DateTime.Now.ToString() + " Shutting Down ---------------------");
                    scheduler.Shutdown(true);
                    log.Info("-----------------" + DateTime.Now.ToString() + " Shutdown Complete -----------------");
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }
    View Code

    Quartz.net的使用可以通过两种方式调用:一是通过代码的方式,而是通过配置文件的方式;

    通过代码的方式虽然很简单,但是也有一个不利点,现在需求有变更,我需要将WithIntervalInSeconds(5) 改成WithIntervalInSeconds(20),也就是每5秒执行一次改成每20秒执行一次,这个就头疼了,你不得不面对改一次需求,就需要编译一次再发布,这样的伤筋动骨;如果用配置文件的话当需求变更的时候我们仅仅需要更改配置文件即可,大大节省了工作量,极力推荐使用配置文件的方式;

    3、创建具体的job类:需要实现IJob接口,并重写它的方法Execute()为具体的业务逻辑

    using Common.Logging;
    using Quartz;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WindowsFormsApplication_1709
    {
        public class PostRawMaterialDistributionPlan : IJob
        {
            public static log4net.ILog log = log4net.LogManager.GetLogger("LogLogger");
            /// <summary>
            /// 作业调度每次要定时执行的方法
            /// </summary>
            /// <param name="context"></param>
            public void Execute(IJobExecutionContext context)
            {
                //ILog log = LogManager.GetLogger(typeof(JobDemo));
    
                DataSet data = SqlHelper.ExecuteDataset(SqlHelper.GetConnSting(), CommandType.StoredProcedure, "P_HTTP_RawMaterialDistributionPlan");
                try
                {
                    log.Info("返回内容:" + ConvertJson.ToJson(data) + "-------------------");
    
                    //以下为示例返回的内容
                    //{ "Table":[
                    //{ "id":"CDAFA658-90C2-4D00-92E3-6E2E206BB358","sale_no":"W240200400201805310001","mat_no":"W240300440","mat_name":"行星轮轴","plan_qty":2,"proline_no":"C001","proline_workpos":"OP101","workpos_assignqty":""},
                    //{ "id":"5DC694BE-46F5-4154-9556-CBF312C0FE0C","sale_no":"W240200400201805310001","mat_no":"W240300442","mat_name":"球面垫片","plan_qty":2,"proline_no":"C001","proline_workpos":"OP101","workpos_assignqty":""},
                    //{ "id":"BB89E5D8-B268-4FAB-BC1F-BF2D93EE9D45","sale_no":"W240200400201805310001","mat_no":"W240300439","mat_name":"行星齿轮","plan_qty":2,"proline_no":"C001","proline_workpos":"OP101","workpos_assignqty":""},
                    //{ "id":"ADC69606-7168-4467-9227-B9287C778258","sale_no":"W240200400201805310001","mat_no":"W240300426","mat_name":"差速器壳","plan_qty":2,"proline_no":"C001","proline_workpos":"OP101","workpos_assignqty":""},
                    //{ "id":"971B4922-5DC5-4D62-A7C6-A62D0208FD9C","sale_no":"W240200400201805310001","mat_no":"W240300441","mat_name":"调整垫片","plan_qty":2,"proline_no":"C001","proline_workpos":"OP101","workpos_assignqty":""},
                    //{ "id":"E6A69690-891A-4307-8324-EAB75A940FAE","sale_no":"W240200400201805310001","mat_no":"W240300381","mat_name":"半轴齿轮","plan_qty":2,"proline_no":"C001","proline_workpos":"OP101","workpos_assignqty":""},
                    //{ "id":"C18A7EE2-6AD0-49FA-8C16-4FB1FE7A668A","sale_no":"W240200400201805310001","mat_no":"W240300429","mat_name":"差速器总成","plan_qty":2,"proline_no":"C001","proline_workpos":"OP102","workpos_assignqty":""},
                    //{ "id":"63190B60-8A5B-4E58-AF25-EDAE1F4023E2","sale_no":"W240200400201805310001","mat_no":"23945465","mat_name":"差速器轴承","plan_qty":2,"proline_no":"C001","proline_workpos":"OP103","workpos_assignqty":""},
                    //{ "id":"EAD94B9F-B7D6-41D2-B789-42446FD59286","sale_no":"W240200400201805310001","mat_no":"W240200426","mat_name":"主动伞齿轮","plan_qty":2,"proline_no":"C001","proline_workpos":"OP103","workpos_assignqty":""},
                    //{ "id":"842B45E8-7B04-4999-8FB9-F5035F724495","sale_no":"W240200400201805310001","mat_no":"9026219","mat_name":"被齿锁紧螺栓","plan_qty":2,"proline_no":"C001","proline_workpos":"OP103","workpos_assignqty":""},
                    //{ "id":"74EF003F-1778-476C-8211-E824ED43D7D8","sale_no":"W240200400201805310001","mat_no":"W240200427","mat_name":"被动伞齿轮","plan_qty":2,"proline_no":"C001","proline_workpos":"OP103","workpos_assignqty":""}]}-------------------
    
                }
                catch (Exception ex)
                {
                    log.Info("返回数据错误:" + ex.InnerException);
                }
            }
        }
    }
    View Code

    通过前面的1、2、3步就完成了通过代码调用;下图是产生的日志文件

    4.通过配置文件方式调用首先启用Form1.ConfigMethod类

    5.创建quartz_jobs.xml文件

    在添加quartz.net引用后还自动添加了“job_scheduling_data_2_0.xsd”文件,它是用来写xml时做代码提示用的!!!需要做一下配置才有提示信息。

    配置过程、选中一个xml文件(例如"quartz_jobs.xml",VS工具栏上会出现XML(X),不选就没有哦!!!)------->>点击XML架构------->>点击添加------->>选中.xsd文件------>>点击打开------>>点击确定!!!完成,绿色框为完成之后的状态,写xml时就有了智能提示了!!

    下面为quartz_jobs.xml的代码

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!-- This file contains job definitions in schema version 2.0 format -->
    
    <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
    
      <processing-directives>
        <overwrite-existing-data>true</overwrite-existing-data>
      </processing-directives>
    
      <schedule>
        <!--SampleJob测试 任务配置-->
        <job>
          <name>SampleJob</name>
          <group>Sample</group>
          <description>SampleJob测试</description>
          <!--job-type节点中定义了需要执行job的命名空间和类名,也是最终schedule需要调度的任务-->
          <job-type>WindowsFormsApplication_1709.PostRawMaterialDistributionPlan, WindowsFormsApplication_1709</job-type>
          <durable>true</durable>
          <recover>false</recover>
        </job>
        <!--每隔3秒执行一次-->
        <trigger>
          <cron>
            <name>SampleJobTrigger</name>
            <group>SampleGroup</group>
            <description>SampleJob</description>
            <job-name>SampleJob</job-name>
            <job-group>Sample</job-group>
            <!--<start-time>2018-05-28T00:00:00+08:00</start-time>-->
            <cron-expression>0/3 * * * * ?</cron-expression>
          </cron>
        </trigger>
      </schedule>
    </job-scheduling-data>
    View Code

    6.修改App.config文件

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
          <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
          <section name="quartz" type="System.Configuration.NameValueSectionHandler"/>
      </configSections>
    
      <log4net>
        <root>
          <level value="ALL" />
          <appender-ref ref="SysAppender" />
        </root>
        <logger name="LogLogger">
          <level value="DEBUG"/>
        </logger>
        <appender name="SysAppender" type="log4net.Appender.RollingFileAppender,log4net" >
          <!--是否追加到文件:日志文件路径,文件夹不存在则新建 -->
          <param name="File" value="logfile.txt" />
          <!--是否追加到文件-->
          <param name="AppendToFile" value="true" />
          <!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <!--使用Unicode编码-->
          <Encoding value="UTF-8" />
          <!--最多产生的日志文件数,超过则只保留最新的n个。设定值value="-1"为不限文件数-->
          <param name="MaxSizeRollBackups" value="10" />
          <!--是否只写到一个文件中-->
          <param name="StaticLogFileName" value="false" />
          <!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
          <param name="RollingStyle" value="Composite" />
          <!--按日期产生文件夹和文件名[在日期方式与混合方式下使用]-->
          <!--此处按日期产生文件夹,文件名固定。注意&quot; 的位置-->
          <param name="DatePattern" value="yyyy-MM-dd/&quot;ReflectionLayout.log&quot;"  />
          <!--这是按日期产生文件夹,并在文件名前也加上日期-->
          <!--<param name="DatePattern" value="yyyyMMdd/yyyyMMdd&quot;-TimerServer.log&quot;"  />-->
          <!--这是先按日期产生文件夹,再形成下一级固定的文件夹-->
          <!--<param name="DatePattern" value="yyyyMMdd/&quot;TimerServer/TimerServer.log&quot;"  />-->
          <!--每个文件的大小:只在混合方式与文件大小方式下使用。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志-->
          <param name="maximumFileSize" value="500KB" />
          <!--计数类型为1,2,3…-->
          <param name="CountDirection" value="1"/>
          <!--记录的格式。一般用log4net.Layout.PatternLayout布局-->
          <layout type="log4net.Layout.PatternLayout,log4net">
            <param name="Header" value="[Header] "/>
            <param name="Footer" value="[Footer] "/>
            <param name="ConversionPattern" value="%d [%t] %-5p %c [%x]  - %m%n" />
          </layout>
          <!--记录的格式。一般用log4net.Layout.PatternLayout布局-->
          <!--用自定义布局测试失败-->
          <!--此处用继承了log4net.Layout.PatternLayout的自定义布局,TGLog.ExpandLayout2为命名空间。%property{Operator}、%property{Action}是自定义的输出-->
          <!--<layout type="TGLog.ExpandLayout2.ReflectionLayout,TGLog">
            <param name="ConversionPattern" value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 记录类:%logger     操作者ID:%property{Operator} 操作类型:%property{Action}%n             当前机器名:%property%n当前机器名及登录用户:%username %n               记录位置:%location%n 消息描述:%property{Message}%n                    异常:%exception%n 消息:%message%newline%n%n" />
          </layout>-->
          <!--过滤设置,LevelRangeFilter为使用的过滤器-->
          <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="DEBUG" />
            <param name="LevelMax" value="WARN" />
          </filter>
        </appender>
        <!--<appender name="ConsoleAppender"  type="log4net.Appender.ConsoleAppender,log4net" >
          <layout type="log4net.Layout.PatternLayout,log4net">
            <param name="ConversionPattern"  value="%d [%t] %-5p %c [%x] - %m%n" />
          </layout>
        </appender>-->
      </log4net>
    
    
    
      <quartz>
        <add key="quartz.scheduler.instanceName" value="ExampleDefaultQuartzScheduler"/>
        <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz"/>
        <add key="quartz.threadPool.threadCount" value="10"/>
        <add key="quartz.threadPool.threadPriority" value="2"/>
        <add key="quartz.jobStore.misfireThreshold" value="60000"/>
        <add key="quartz.jobStore.type" value="Quartz.Simpl.RAMJobStore, Quartz"/>
        <!--******************************Plugin配置*********************************************-->
        <add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" />
        <add key="quartz.plugin.xml.fileNames" value="~/quartz_jobs.xml"/>
      </quartz>
    
    
      <connectionStrings>
        <add name="ConnectionStringMain" connectionString="Data Source=192.168.1.211;Initial Catalog=WLZhuJianMes;Persist Security Info=True;User ID=sa;Password=sa;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
      </connectionStrings>
      
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
      
    </configuration>
    View Code

    由于我无论是通过代码方式调用还是配置文件方式调用,具体的job都用的是同一个PostRawMaterialDistributionPlan,所以再次经过后面几部的过程通过配置文件的方式调用就完成了。下图为返回内容的日志,两者没有差别的。

    附录:

    1、SqlHelper类

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml;
    
    namespace WindowsFormsApplication_1709
    {
        public sealed class SqlHelper
        {
            #region 私有构造函数和方法
    
            private SqlHelper() { }
    
            /// <summary>   
            /// 将SqlParameter参数数组(参数值)分配给SqlCommand命令.   
            /// 这个方法将给任何一个参数分配DBNull.Value;   
            /// 该操作将阻止默认值的使用.   
            /// </summary>   
            /// <param name="command">命令名</param>   
            /// <param name="commandParameters">SqlParameters数组</param>   
            private static void AttachParameters(SqlCommand command, SqlParameter[] commandParameters)
            {
                if (command == null) throw new ArgumentNullException("command");
                if (commandParameters != null)
                {
                    foreach (SqlParameter p in commandParameters)
                    {
                        if (p != null)
                        {
                            // 检查未分配值的输出参数,将其分配以DBNull.Value.   
                            if ((p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Input) &&
                                (p.Value == null))
                            {
                                p.Value = DBNull.Value;
                            }
                            command.Parameters.Add(p);
                        }
                    }
                }
            }
    
            /// <summary>   
            /// 将DataRow类型的列值分配到SqlParameter参数数组.   
            /// </summary>   
            /// <param name="commandParameters">要分配值的SqlParameter参数数组</param>   
            /// <param name="dataRow">将要分配给存储过程参数的DataRow</param>   
            private static void AssignParameterValues(SqlParameter[] commandParameters, DataRow dataRow)
            {
                if ((commandParameters == null) || (dataRow == null))
                {
                    return;
                }
    
                int i = 0;
                // 设置参数值   
                foreach (SqlParameter commandParameter in commandParameters)
                {
                    // 创建参数名称,如果不存在,只抛出一个异常.   
                    if (commandParameter.ParameterName == null ||
                        commandParameter.ParameterName.Length <= 1)
                        throw new Exception(
                            string.Format("请提供参数{0}一个有效的名称{1}.", i, commandParameter.ParameterName));
                    // 从dataRow的表中获取为参数数组中数组名称的列的索引.   
                    // 如果存在和参数名称相同的列,则将列值赋给当前名称的参数.   
                    if (dataRow.Table.Columns.IndexOf(commandParameter.ParameterName.Substring(1)) != -1)
                        commandParameter.Value = dataRow[commandParameter.ParameterName.Substring(1)];
                    i++;
                }
            }
    
            /// <summary>   
            /// 将一个对象数组分配给SqlParameter参数数组.   
            /// </summary>   
            /// <param name="commandParameters">要分配值的SqlParameter参数数组</param>   
            /// <param name="parameterValues">将要分配给存储过程参数的对象数组</param>   
            private static void AssignParameterValues(SqlParameter[] commandParameters, object[] parameterValues)
            {
                if ((commandParameters == null) || (parameterValues == null))
                {
                    return;
                }
    
                // 确保对象数组个数与参数个数匹配,如果不匹配,抛出一个异常.   
                if (commandParameters.Length != parameterValues.Length)
                {
                    throw new ArgumentException("参数值个数与参数不匹配.");
                }
    
                // 给参数赋值   
                for (int i = 0, j = commandParameters.Length; i < j; i++)
                {
                    // If the current array value derives from IDbDataParameter, then assign its Value property   
                    if (parameterValues[i] is IDbDataParameter)
                    {
                        IDbDataParameter paramInstance = (IDbDataParameter)parameterValues[i];
                        if (paramInstance.Value == null)
                        {
                            commandParameters[i].Value = DBNull.Value;
                        }
                        else
                        {
                            commandParameters[i].Value = paramInstance.Value;
                        }
                    }
                    else if (parameterValues[i] == null)
                    {
                        commandParameters[i].Value = DBNull.Value;
                    }
                    else
                    {
                        commandParameters[i].Value = parameterValues[i];
                    }
                }
            }
    
            /// <summary>   
            /// 预处理用户提供的命令,数据库连接/事务/命令类型/参数   
            /// </summary>   
            /// <param name="command">要处理的SqlCommand</param>   
            /// <param name="connection">数据库连接</param>   
            /// <param name="transaction">一个有效的事务或者是null值</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本, 其它.)</param>   
            /// <param name="commandText">存储过程名或都T-SQL命令文本</param>   
            /// <param name="commandParameters">和命令相关联的SqlParameter参数数组,如果没有参数为'null'</param>   
            /// <param name="mustCloseConnection"><c>true</c> 如果连接是打开的,则为true,其它情况下为false.</param>   
            private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, out bool mustCloseConnection)
            {
                if (command == null) throw new ArgumentNullException("command");
                if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
    
                // If the provided connection is not open, we will open it   
                if (connection.State != ConnectionState.Open)
                {
                    mustCloseConnection = true;
                    connection.Open();
                }
                else
                {
                    mustCloseConnection = false;
                }
    
                // 给命令分配一个数据库连接.   
                command.Connection = connection;
    
                // 设置命令文本(存储过程名或SQL语句)   
                command.CommandText = commandText;
    
                // 分配事务   
                if (transaction != null)
                {
                    if (transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                    command.Transaction = transaction;
                }
    
                // 设置命令类型.   
                command.CommandType = commandType;
    
                // 分配命令参数   
                if (commandParameters != null)
                {
                    AttachParameters(command, commandParameters);
                }
                return;
            }
    
            #endregion 私有构造函数和方法结束
    
            #region 数据库连接
            /// <summary>   
            /// 一个有效的数据库连接字符串   
            /// </summary>   
            /// <returns></returns>   
            public static string GetConnSting()
            {
                return ConfigurationManager.ConnectionStrings["ConnectionStringMain"].ConnectionString;
            }
            /// <summary>   
            /// 一个有效的数据库连接对象   
            /// </summary>   
            /// <returns></returns>   
            public static SqlConnection GetConnection()
            {
                SqlConnection Connection = new SqlConnection(SqlHelper.GetConnSting());
                return Connection;
            }
            #endregion
    
            #region ExecuteNonQuery命令
    
            /// <summary>   
            /// 执行指定连接字符串,类型的SqlCommand.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders");   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本, 其它.)</param>   
            /// <param name="commandText">存储过程名称或SQL语句</param>   
            /// <returns>返回命令影响的行数</returns>   
            public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText)
            {
                return ExecuteNonQuery(connectionString, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定连接字符串,类型的SqlCommand.如果没有提供参数,不返回结果.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本, 其它.)</param>   
            /// <param name="commandText">存储过程名称或SQL语句</param>   
            /// <param name="commandParameters">SqlParameter参数数组</param>   
            /// <returns>返回命令影响的行数</returns>   
            public static int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    return ExecuteNonQuery(connection, commandType, commandText, commandParameters);
                }
            }
    
            /// <summary>   
            /// 执行指定连接字符串的存储过程,将对象数组的值赋给存储过程参数,   
            /// 此方法需要在参数缓存方法中探索参数并生成参数.   
            /// </summary>   
            /// <remarks>   
            /// 这个方法没有提供访问输出参数和返回值.   
            /// 示例:    
            ///  int result = ExecuteNonQuery(connString, "PublishOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串/param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="parameterValues">分配到存储过程输入参数的对象数组</param>   
            /// <returns>返回受影响的行数</returns>   
            public static int ExecuteNonQuery(string connectionString, string spName, params object[] parameterValues)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果存在参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从探索存储过程参数(加载到缓存)并分配给存储过程参数数组.   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数情况下   
                    return ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders");   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型(存储过程,命令文本或其它.)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText)
            {
                return ExecuteNonQuery(connection, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型(存储过程,命令文本或其它.)</param>   
            /// <param name="commandText">T存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParamter参数数组</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQuery(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connection == null) throw new ArgumentNullException("connection");
    
                // 创建SqlCommand命令,并进行预处理   
                SqlCommand cmd = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // Finally, execute the command   
                int retval = cmd.ExecuteNonQuery();
    
                // 清除参数,以便再次使用.   
                cmd.Parameters.Clear();
                if (mustCloseConnection)
                    connection.Close();
                return retval;
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,将对象数组的值赋给存储过程参数.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值   
            /// 示例:    
            ///  int result = ExecuteNonQuery(conn, "PublishOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQuery(SqlConnection connection, string spName, params object[] parameterValues)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 给存储过程分配参数值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return ExecuteNonQuery(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行带事务的SqlCommand.   
            /// </summary>   
            /// <remarks>   
            /// 示例.:    
            ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders");   
            /// </remarks>   
            /// <param name="transaction">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型(存储过程,命令文本或其它.)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回影响的行数/returns>   
            public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText)
            {
                return ExecuteNonQuery(transaction, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行带事务的SqlCommand(指定参数).   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="transaction">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型(存储过程,命令文本或其它.)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParamter参数数组</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQuery(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    
                // 预处理   
                SqlCommand cmd = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 执行   
                int retval = cmd.ExecuteNonQuery();
    
                // 清除参数集,以便再次使用.   
                cmd.Parameters.Clear();
                return retval;
            }
    
            /// <summary>   
            /// 执行带事务的SqlCommand(指定参数值).   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值   
            /// 示例:    
            ///  int result = ExecuteNonQuery(conn, trans, "PublishOrders", 24, 36);   
            /// </remarks>   
            /// <param name="transaction">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回受影响的行数</returns>   
            public static int ExecuteNonQuery(SqlTransaction transaction, string spName, params object[] parameterValues)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
                }
            }
    
            #endregion ExecuteNonQuery方法结束
    
            #region ExecuteDataset方法
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText)
            {
                return ExecuteDataset(connectionString, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 示例:   
            ///  DataSet ds = ExecuteDataset(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParamters参数数组</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
    
                // 创建并打开数据库连接对象,操作完成释放对象.   
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    // 调用指定数据库连接字符串重载方法.   
                    return ExecuteDataset(connection, commandType, commandText, commandParameters);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,直接提供参数值,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值.   
            /// 示例:   
            ///  DataSet ds = ExecuteDataset(connString, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(string connectionString, string spName, params object[] parameterValues)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中检索存储过程参数   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 给存储过程参数分配值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return ExecuteDataset(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText)
            {
                return ExecuteDataset(connection, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,指定存储过程参数,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  DataSet ds = ExecuteDataset(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParamter参数数组</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connection == null) throw new ArgumentNullException("connection");
    
                // 预处理   
                SqlCommand cmd = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 创建SqlDataAdapter和DataSet.   
                using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                {
                    DataSet ds = new DataSet();
    
                    // 填充DataSet.   
                    da.Fill(ds);
    
                    cmd.Parameters.Clear();
    
                    if (mustCloseConnection)
                        connection.Close();
    
                    return ds;
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,指定参数值,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输入参数和返回值.   
            /// 示例.:    
            ///  DataSet ds = ExecuteDataset(conn, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(SqlConnection connection, string spName, params object[] parameterValues)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 比缓存中加载存储过程参数   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 给存储过程参数分配值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteDataset(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return ExecuteDataset(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定事务的命令,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="transaction">事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText)
            {
                return ExecuteDataset(transaction, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定事务的命令,指定参数,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  DataSet ds = ExecuteDataset(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="transaction">事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParamter参数数组</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    
                // 预处理   
                SqlCommand cmd = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 创建 DataAdapter & DataSet   
                using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                {
                    DataSet ds = new DataSet();
                    da.Fill(ds);
                    cmd.Parameters.Clear();
                    return ds;
                }
            }
    
            /// <summary>   
            /// 执行指定事务的命令,指定参数值,返回DataSet.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输入参数和返回值.   
            /// 示例.:    
            ///  DataSet ds = ExecuteDataset(trans, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="transaction">事务</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回一个包含结果集的DataSet</returns>   
            public static DataSet ExecuteDataset(SqlTransaction transaction, string spName, params object[] parameterValues)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 给存储过程参数分配值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteDataset(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return ExecuteDataset(transaction, CommandType.StoredProcedure, spName);
                }
            }
    
            #endregion ExecuteDataset数据集命令结束
    
            #region ExecuteReader 数据阅读器
    
            /// <summary>   
            /// 枚举,标识数据库连接是由SqlHelper提供还是由调用者提供   
            /// </summary>   
            private enum SqlConnectionOwnership
            {
                /// <summary>由SqlHelper提供连接</summary>   
                Internal,
                /// <summary>由调用者提供连接</summary>   
                External
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的数据阅读器.   
            /// </summary>   
            /// <remarks>   
            /// 如果是SqlHelper打开连接,当连接关闭DataReader也将关闭.   
            /// 如果是调用都打开连接,DataReader由调用都管理.   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="transaction">一个有效的事务,或者为 'null'</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParameters参数数组,如果没有参数则为'null'</param>   
            /// <param name="connectionOwnership">标识数据库连接对象是由调用者提供还是由SqlHelper提供</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            private static SqlDataReader ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership)
            {
                if (connection == null) throw new ArgumentNullException("connection");
    
                bool mustCloseConnection = false;
                // 创建命令   
                SqlCommand cmd = new SqlCommand();
                try
                {
                    PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    
                    // 创建数据阅读器   
                    SqlDataReader dataReader;
    
                    if (connectionOwnership == SqlConnectionOwnership.External)
                    {
                        dataReader = cmd.ExecuteReader();
                    }
                    else
                    {
                        dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    }
    
                    // 清除参数,以便再次使用..   
                    // HACK: There is a problem here, the output parameter values are fletched   
                    // when the reader is closed, so if the parameters are detached from the command   
                    // then the SqlReader can磘 set its values.   
                    // When this happen, the parameters can磘 be used again in other command.   
                    bool canClear = true;
                    foreach (SqlParameter commandParameter in cmd.Parameters)
                    {
                        if (commandParameter.Direction != ParameterDirection.Input)
                            canClear = false;
                    }
    
                    if (canClear)
                    {
                        cmd.Parameters.Clear();
                    }
    
                    return dataReader;
                }
                catch
                {
                    if (mustCloseConnection)
                        connection.Close();
                    throw;
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的数据阅读器.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText)
            {
                return ExecuteReader(connectionString, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的数据阅读器,指定参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(connString, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <param name="commandParameters">SqlParamter参数数组(new SqlParameter("@prodid", 24))</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                SqlConnection connection = null;
                try
                {
                    connection = new SqlConnection(connectionString);
                    connection.Open();
    
                    return ExecuteReader(connection, null, commandType, commandText, commandParameters, SqlConnectionOwnership.Internal);
                }
                catch
                {
                    // If we fail to return the SqlDatReader, we need to close the connection ourselves   
                    if (connection != null) connection.Close();
                    throw;
                }
    
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的数据阅读器,指定参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(connString, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(string connectionString, string spName, params object[] parameterValues)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return ExecuteReader(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的数据阅读器.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名或T-SQL语句</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText)
            {
                return ExecuteReader(connection, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// [调用者方式]执行指定数据库连接对象的数据阅读器,指定参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandParameters">SqlParamter参数数组</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                return ExecuteReader(connection, (SqlTransaction)null, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
            }
    
            /// <summary>   
            /// [调用者方式]执行指定数据库连接对象的数据阅读器,指定参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(conn, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">T存储过程名</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(SqlConnection connection, string spName, params object[] parameterValues)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteReader(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return ExecuteReader(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// [调用者方式]执行指定数据库事务的数据阅读器,指定参数值.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText)
            {
                return ExecuteReader(transaction, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// [调用者方式]执行指定数据库事务的数据阅读器,指定参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///   SqlDataReader dr = ExecuteReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    
                return ExecuteReader(transaction.Connection, transaction, commandType, commandText, commandParameters, SqlConnectionOwnership.External);
            }
    
            /// <summary>   
            /// [调用者方式]执行指定数据库事务的数据阅读器,指定参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  SqlDataReader dr = ExecuteReader(trans, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReader(SqlTransaction transaction, string spName, params object[] parameterValues)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    AssignParameterValues(commandParameters, parameterValues);
    
                    return ExecuteReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteReader(transaction, CommandType.StoredProcedure, spName);
                }
            }
    
            #endregion ExecuteReader数据阅读器
    
            #region ExecuteScalar 返回结果集中的第一行第一列
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount");   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText)
            {
                // 执行参数为空的方法   
                return ExecuteScalar(connectionString, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,指定参数,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(connString, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(string connectionString, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                // 创建并打开数据库连接对象,操作完成释放对象.   
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    // 调用指定数据库连接字符串重载方法.   
                    return ExecuteScalar(connection, commandType, commandText, commandParameters);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,指定参数值,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(connString, "GetOrderCount", 24, 36);   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(string connectionString, string spName, params object[] parameterValues)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteScalar(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount");   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText)
            {
                // 执行参数为空的方法   
                return ExecuteScalar(connection, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,指定参数,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(conn, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connection == null) throw new ArgumentNullException("connection");
    
                // 创建SqlCommand命令,并进行预处理   
                SqlCommand cmd = new SqlCommand();
    
                bool mustCloseConnection = false;
                PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 执行SqlCommand命令,并返回结果.   
                object retval = cmd.ExecuteScalar();
    
                // 清除参数,以便再次使用.   
                cmd.Parameters.Clear();
    
                if (mustCloseConnection)
                    connection.Close();
    
                return retval;
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,指定参数值,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(conn, "GetOrderCount", 24, 36);   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(SqlConnection connection, string spName, params object[] parameterValues)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    return ExecuteScalar(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteScalar(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库事务的命令,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount");   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText)
            {
                // 执行参数为空的方法   
                return ExecuteScalar(transaction, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库事务的命令,指定参数,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(trans, CommandType.StoredProcedure, "GetOrderCount", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    
                // 创建SqlCommand命令,并进行预处理   
                SqlCommand cmd = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 执行SqlCommand命令,并返回结果.   
                object retval = cmd.ExecuteScalar();
    
                // 清除参数,以便再次使用.   
                cmd.Parameters.Clear();
                return retval;
            }
    
            /// <summary>   
            /// 执行指定数据库事务的命令,指定参数值,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  int orderCount = (int)ExecuteScalar(trans, "GetOrderCount", 24, 36);   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalar(SqlTransaction transaction, string spName, params object[] parameterValues)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // PPull the parameters for this stored procedure from the parameter cache ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    return ExecuteScalar(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteScalar(transaction, CommandType.StoredProcedure, spName);
                }
            }
    
            #endregion ExecuteScalar
    
            #region ExecuteXmlReader XML阅读器
            /// <summary>   
            /// 执行指定数据库连接对象的SqlCommand命令,并产生一个XmlReader对象做为结果集返回.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句 using "FOR XML AUTO"</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText)
            {
                // 执行参数为空的方法   
                return ExecuteXmlReader(connection, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的SqlCommand命令,并产生一个XmlReader对象做为结果集返回,指定参数.  
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  XmlReader r = ExecuteXmlReader(conn, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句 using "FOR XML AUTO"</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReader(SqlConnection connection, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (connection == null) throw new ArgumentNullException("connection");
    
                bool mustCloseConnection = false;
                // 创建SqlCommand命令,并进行预处理   
                SqlCommand cmd = new SqlCommand();
                try
                {
                    PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
    
                    // 执行命令   
                    XmlReader retval = cmd.ExecuteXmlReader();
    
                    // 清除参数,以便再次使用.   
                    cmd.Parameters.Clear();
    
                    return retval;
                }
                catch
                {
                    if (mustCloseConnection)
                        connection.Close();
                    throw;
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的SqlCommand命令,并产生一个XmlReader对象做为结果集返回,指定参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  XmlReader r = ExecuteXmlReader(conn, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称 using "FOR XML AUTO"</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReader(SqlConnection connection, string spName, params object[] parameterValues)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteXmlReader(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库事务的SqlCommand命令,并产生一个XmlReader对象做为结果集返回.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders");   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句 using "FOR XML AUTO"</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText)
            {
                // 执行参数为空的方法   
                return ExecuteXmlReader(transaction, commandType, commandText, (SqlParameter[])null);
            }
    
            /// <summary>   
            /// 执行指定数据库事务的SqlCommand命令,并产生一个XmlReader对象做为结果集返回,指定参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  XmlReader r = ExecuteXmlReader(trans, CommandType.StoredProcedure, "GetOrders", new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句 using "FOR XML AUTO"</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReader(SqlTransaction transaction, CommandType commandType, string commandText, params SqlParameter[] commandParameters)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
    
                // 创建SqlCommand命令,并进行预处理   
                SqlCommand cmd = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(cmd, transaction.Connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 执行命令   
                XmlReader retval = cmd.ExecuteXmlReader();
    
                // 清除参数,以便再次使用.   
                cmd.Parameters.Clear();
                return retval;
            }
    
            /// <summary>   
            /// 执行指定数据库事务的SqlCommand命令,并产生一个XmlReader对象做为结果集返回,指定参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  XmlReader r = ExecuteXmlReader(trans, "GetOrders", 24, 36);   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            /// <returns>返回一个包含结果集的DataSet.</returns>   
            public static XmlReader ExecuteXmlReader(SqlTransaction transaction, string spName, params object[] parameterValues)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    return ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName);
                }
            }
    
            #endregion ExecuteXmlReader 阅读器结束
    
            #region FillDataset 填充数据集
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,映射数据表并填充数据集.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(connString, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"});   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)</param>   
            public static void FillDataset(string connectionString, CommandType commandType, string commandText, DataSet dataSet, string[] tableNames)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (dataSet == null) throw new ArgumentNullException("dataSet");
    
                // 创建并打开数据库连接对象,操作完成释放对象.   
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    // 调用指定数据库连接字符串重载方法.   
                    FillDataset(connection, commandType, commandText, dataSet, tableNames);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,映射数据表并填充数据集.指定命令参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(connString, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            public static void FillDataset(string connectionString, CommandType commandType,
                string commandText, DataSet dataSet, string[] tableNames,
                params SqlParameter[] commandParameters)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (dataSet == null) throw new ArgumentNullException("dataSet");
                // 创建并打开数据库连接对象,操作完成释放对象.   
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    // 调用指定数据库连接字符串重载方法.   
                    FillDataset(connection, commandType, commandText, dataSet, tableNames, commandParameters);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接字符串的命令,映射数据表并填充数据集,指定存储过程参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  FillDataset(connString, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, 24);   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>      
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            public static void FillDataset(string connectionString, string spName,
                DataSet dataSet, string[] tableNames,
                params object[] parameterValues)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (dataSet == null) throw new ArgumentNullException("dataSet");
                // 创建并打开数据库连接对象,操作完成释放对象.   
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    // 调用指定数据库连接字符串重载方法.   
                    FillDataset(connection, spName, dataSet, tableNames, parameterValues);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,映射数据表并填充数据集.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(conn, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"});   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>      
            public static void FillDataset(SqlConnection connection, CommandType commandType,
                string commandText, DataSet dataSet, string[] tableNames)
            {
                FillDataset(connection, commandType, commandText, dataSet, tableNames, null);
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,映射数据表并填充数据集,指定参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(conn, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            public static void FillDataset(SqlConnection connection, CommandType commandType,
                string commandText, DataSet dataSet, string[] tableNames,
                params SqlParameter[] commandParameters)
            {
                FillDataset(connection, null, commandType, commandText, dataSet, tableNames, commandParameters);
            }
    
            /// <summary>   
            /// 执行指定数据库连接对象的命令,映射数据表并填充数据集,指定存储过程参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  FillDataset(conn, "GetOrders", ds, new string[] {"orders"}, 24, 36);   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            public static void FillDataset(SqlConnection connection, string spName,
                DataSet dataSet, string[] tableNames,
                params object[] parameterValues)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (dataSet == null) throw new ArgumentNullException("dataSet");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    FillDataset(connection, CommandType.StoredProcedure, spName, dataSet, tableNames, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    FillDataset(connection, CommandType.StoredProcedure, spName, dataSet, tableNames);
                }
            }
    
            /// <summary>   
            /// 执行指定数据库事务的命令,映射数据表并填充数据集.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(trans, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"});   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            public static void FillDataset(SqlTransaction transaction, CommandType commandType,
                string commandText,
                DataSet dataSet, string[] tableNames)
            {
                FillDataset(transaction, commandType, commandText, dataSet, tableNames, null);
            }
    
            /// <summary>   
            /// 执行指定数据库事务的命令,映射数据表并填充数据集,指定参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(trans, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            public static void FillDataset(SqlTransaction transaction, CommandType commandType,
                string commandText, DataSet dataSet, string[] tableNames,
                params SqlParameter[] commandParameters)
            {
                FillDataset(transaction.Connection, transaction, commandType, commandText, dataSet, tableNames, commandParameters);
            }
    
            /// <summary>   
            /// 执行指定数据库事务的命令,映射数据表并填充数据集,指定存储过程参数值.   
            /// </summary>   
            /// <remarks>   
            /// 此方法不提供访问存储过程输出参数和返回值参数.   
            ///   
            /// 示例:    
            ///  FillDataset(trans, "GetOrders", ds, new string[]{"orders"}, 24, 36);   
            /// </remarks>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            /// <param name="parameterValues">分配给存储过程输入参数的对象数组</param>   
            public static void FillDataset(SqlTransaction transaction, string spName,
                DataSet dataSet, string[] tableNames,
                params object[] parameterValues)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (dataSet == null) throw new ArgumentNullException("dataSet");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果有参数值   
                if ((parameterValues != null) && (parameterValues.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 给存储过程参数赋值   
                    AssignParameterValues(commandParameters, parameterValues);
    
                    // 调用重载方法   
                    FillDataset(transaction, CommandType.StoredProcedure, spName, dataSet, tableNames, commandParameters);
                }
                else
                {
                    // 没有参数值   
                    FillDataset(transaction, CommandType.StoredProcedure, spName, dataSet, tableNames);
                }
            }
    
            /// <summary>   
            /// [私有方法][内部调用]执行指定数据库连接对象/事务的命令,映射数据表并填充数据集,DataSet/TableNames/SqlParameters.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  FillDataset(conn, trans, CommandType.StoredProcedure, "GetOrders", ds, new string[] {"orders"}, new SqlParameter("@prodid", 24));   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="transaction">一个有效的连接事务</param>   
            /// <param name="commandType">命令类型 (存储过程,命令文本或其它)</param>   
            /// <param name="commandText">存储过程名称或T-SQL语句</param>   
            /// <param name="dataSet">要填充结果集的DataSet实例</param>   
            /// <param name="tableNames">表映射的数据表数组   
            /// 用户定义的表名 (可有是实际的表名.)   
            /// </param>   
            /// <param name="commandParameters">分配给命令的SqlParamter参数数组</param>   
            private static void FillDataset(SqlConnection connection, SqlTransaction transaction, CommandType commandType,
                string commandText, DataSet dataSet, string[] tableNames,
                params SqlParameter[] commandParameters)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (dataSet == null) throw new ArgumentNullException("dataSet");
    
                // 创建SqlCommand命令,并进行预处理   
                SqlCommand command = new SqlCommand();
                bool mustCloseConnection = false;
                PrepareCommand(command, connection, transaction, commandType, commandText, commandParameters, out mustCloseConnection);
    
                // 执行命令   
                using (SqlDataAdapter dataAdapter = new SqlDataAdapter(command))
                {
    
                    // 追加表映射   
                    if (tableNames != null && tableNames.Length > 0)
                    {
                        string tableName = "Table";
                        for (int index = 0; index < tableNames.Length; index++)
                        {
                            if (tableNames[index] == null || tableNames[index].Length == 0) throw new ArgumentException("The tableNames parameter must contain a list of tables, a value was provided as null or empty string.", "tableNames");
                            dataAdapter.TableMappings.Add(tableName, tableNames[index]);
                            tableName += (index + 1).ToString();
                        }
                    }
    
                    // 填充数据集使用默认表名称   
                    dataAdapter.Fill(dataSet);
    
                    // 清除参数,以便再次使用.   
                    command.Parameters.Clear();
                }
    
                if (mustCloseConnection)
                    connection.Close();
            }
            #endregion
    
            #region UpdateDataset 更新数据集
            /// <summary>   
            /// 执行数据集更新到数据库,指定inserted, updated, or deleted命令.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  UpdateDataset(conn, insertCommand, deleteCommand, updateCommand, dataSet, "Order");   
            /// </remarks>   
            /// <param name="insertCommand">[追加记录]一个有效的T-SQL语句或存储过程</param>   
            /// <param name="deleteCommand">[删除记录]一个有效的T-SQL语句或存储过程</param>   
            /// <param name="updateCommand">[更新记录]一个有效的T-SQL语句或存储过程</param>   
            /// <param name="dataSet">要更新到数据库的DataSet</param>   
            /// <param name="tableName">要更新到数据库的DataTable</param>   
            public static void UpdateDataset(SqlCommand insertCommand, SqlCommand deleteCommand, SqlCommand updateCommand, DataSet dataSet, string tableName)
            {
                if (insertCommand == null) throw new ArgumentNullException("insertCommand");
                if (deleteCommand == null) throw new ArgumentNullException("deleteCommand");
                if (updateCommand == null) throw new ArgumentNullException("updateCommand");
                if (tableName == null || tableName.Length == 0) throw new ArgumentNullException("tableName");
    
                // 创建SqlDataAdapter,当操作完成后释放.   
                using (SqlDataAdapter dataAdapter = new SqlDataAdapter())
                {
                    // 设置数据适配器命令   
                    dataAdapter.UpdateCommand = updateCommand;
                    dataAdapter.InsertCommand = insertCommand;
                    dataAdapter.DeleteCommand = deleteCommand;
    
                    // 更新数据集改变到数据库   
                    dataAdapter.Update(dataSet, tableName);
    
                    // 提交所有改变到数据集.   
                    dataSet.AcceptChanges();
                }
            }
            #endregion
    
            #region CreateCommand 创建一条SqlCommand命令
            /// <summary>   
            /// 创建SqlCommand命令,指定数据库连接对象,存储过程名和参数.   
            /// </summary>   
            /// <remarks>   
            /// 示例:    
            ///  SqlCommand command = CreateCommand(conn, "AddCustomer", "CustomerID", "CustomerName");   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="sourceColumns">源表的列名称数组</param>   
            /// <returns>返回SqlCommand命令</returns>   
            public static SqlCommand CreateCommand(SqlConnection connection, string spName, params string[] sourceColumns)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 创建命令   
                SqlCommand cmd = new SqlCommand(spName, connection);
                cmd.CommandType = CommandType.StoredProcedure;
    
                // 如果有参数值   
                if ((sourceColumns != null) && (sourceColumns.Length > 0))
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 将源表的列到映射到DataSet命令中.   
                    for (int index = 0; index < sourceColumns.Length; index++)
                        commandParameters[index].SourceColumn = sourceColumns[index];
    
                    // Attach the discovered parameters to the SqlCommand object   
                    AttachParameters(cmd, commandParameters);
                }
    
                return cmd;
            }
            #endregion
    
            #region ExecuteNonQueryTypedParams 类型化参数(DataRow)
            /// <summary>   
            /// 执行指定连接数据库连接字符串的存储过程,使用DataRow做为参数值,返回受影响的行数.   
            /// </summary>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQueryTypedParams(String connectionString, String spName, DataRow dataRow)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库连接对象的存储过程,使用DataRow做为参数值,返回受影响的行数.   
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQueryTypedParams(SqlConnection connection, String spName, DataRow dataRow)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteNonQuery(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteNonQuery(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库事物的存储过程,使用DataRow做为参数值,返回受影响的行数.   
            /// </summary>   
            /// <param name="transaction">一个有效的连接事务 object</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回影响的行数</returns>   
            public static int ExecuteNonQueryTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // Sf the row has values, the store procedure parameters must be initialized   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
                }
            }
            #endregion
    
            #region ExecuteDatasetTypedParams 类型化参数(DataRow)
            /// <summary>   
            /// 执行指定连接数据库连接字符串的存储过程,使用DataRow做为参数值,返回DataSet.   
            /// </summary>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回一个包含结果集的DataSet.</returns>   
            public static DataSet ExecuteDatasetTypedParams(string connectionString, String spName, DataRow dataRow)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                //如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库连接对象的存储过程,使用DataRow做为参数值,返回DataSet.   
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回一个包含结果集的DataSet.</returns>   
            ///   
            public static DataSet ExecuteDatasetTypedParams(SqlConnection connection, String spName, DataRow dataRow)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteDataset(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteDataset(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库事务的存储过程,使用DataRow做为参数值,返回DataSet.   
            /// </summary>   
            /// <param name="transaction">一个有效的连接事务 object</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回一个包含结果集的DataSet.</returns>   
            public static DataSet ExecuteDatasetTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteDataset(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteDataset(transaction, CommandType.StoredProcedure, spName);
                }
            }
    
            #endregion
    
            #region ExecuteReaderTypedParams 类型化参数(DataRow)
            /// <summary>   
            /// 执行指定连接数据库连接字符串的存储过程,使用DataRow做为参数值,返回DataReader.   
            /// </summary>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReaderTypedParams(String connectionString, String spName, DataRow dataRow)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteReader(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteReader(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
    
            /// <summary>   
            /// 执行指定连接数据库连接对象的存储过程,使用DataRow做为参数值,返回DataReader.   
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReaderTypedParams(SqlConnection connection, String spName, DataRow dataRow)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteReader(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteReader(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库事物的存储过程,使用DataRow做为参数值,返回DataReader.   
            /// </summary>   
            /// <param name="transaction">一个有效的连接事务 object</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回包含结果集的SqlDataReader</returns>   
            public static SqlDataReader ExecuteReaderTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteReader(transaction, CommandType.StoredProcedure, spName);
                }
            }
            #endregion
    
            #region ExecuteScalarTypedParams 类型化参数(DataRow)
            /// <summary>   
            /// 执行指定连接数据库连接字符串的存储过程,使用DataRow做为参数值,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalarTypedParams(String connectionString, String spName, DataRow dataRow)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteScalar(connectionString, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteScalar(connectionString, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库连接对象的存储过程,使用DataRow做为参数值,返回结果集中的第一行第一列.  
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalarTypedParams(SqlConnection connection, String spName, DataRow dataRow)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteScalar(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteScalar(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库事务的存储过程,使用DataRow做为参数值,返回结果集中的第一行第一列.   
            /// </summary>   
            /// <param name="transaction">一个有效的连接事务 object</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回结果集中的第一行第一列</returns>   
            public static object ExecuteScalarTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteScalar(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteScalar(transaction, CommandType.StoredProcedure, spName);
                }
            }
            #endregion
    
            #region ExecuteXmlReaderTypedParams 类型化参数(DataRow)
            /// <summary>   
            /// 执行指定连接数据库连接对象的存储过程,使用DataRow做为参数值,返回XmlReader类型的结果集.   
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReaderTypedParams(SqlConnection connection, String spName, DataRow dataRow)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteXmlReader(connection, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteXmlReader(connection, CommandType.StoredProcedure, spName);
                }
            }
    
            /// <summary>   
            /// 执行指定连接数据库事务的存储过程,使用DataRow做为参数值,返回XmlReader类型的结果集.   
            /// </summary>   
            /// <param name="transaction">一个有效的连接事务 object</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="dataRow">使用DataRow作为参数值</param>   
            /// <returns>返回XmlReader结果集对象.</returns>   
            public static XmlReader ExecuteXmlReaderTypedParams(SqlTransaction transaction, String spName, DataRow dataRow)
            {
                if (transaction == null) throw new ArgumentNullException("transaction");
                if (transaction != null && transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                // 如果row有值,存储过程必须初始化.   
                if (dataRow != null && dataRow.ItemArray.Length > 0)
                {
                    // 从缓存中加载存储过程参数,如果缓存中不存在则从数据库中检索参数信息并加载到缓存中. ()   
                    SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection, spName);
    
                    // 分配参数值   
                    AssignParameterValues(commandParameters, dataRow);
    
                    return SqlHelper.ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName, commandParameters);
                }
                else
                {
                    return SqlHelper.ExecuteXmlReader(transaction, CommandType.StoredProcedure, spName);
                }
            }
            #endregion
    
        }
    
        /// <summary>   
        /// SqlHelperParameterCache提供缓存存储过程参数,并能够在运行时从存储过程中探索参数.   
        /// </summary>   
        public sealed class SqlHelperParameterCache
        {
            #region 私有方法,字段,构造函数
            // 私有构造函数,妨止类被实例化.   
            private SqlHelperParameterCache() { }
    
            // 这个方法要注意   
            private static Hashtable paramCache = Hashtable.Synchronized(new Hashtable());
    
            /// <summary>   
            /// 探索运行时的存储过程,返回SqlParameter参数数组.   
            /// 初始化参数值为 DBNull.Value.   
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接</param>   
            /// <param name="spName">存储过程名称</param>   
            /// <param name="includeReturnValueParameter">是否包含返回值参数</param>   
            /// <returns>返回SqlParameter参数数组</returns>   
            private static SqlParameter[] DiscoverSpParameterSet(SqlConnection connection, string spName, bool includeReturnValueParameter)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                SqlCommand cmd = new SqlCommand(spName, connection);
                cmd.CommandType = CommandType.StoredProcedure;
    
                connection.Open();
                // 检索cmd指定的存储过程的参数信息,并填充到cmd的Parameters参数集中.   
                SqlCommandBuilder.DeriveParameters(cmd);
                connection.Close();
                // 如果不包含返回值参数,将参数集中的每一个参数删除.   
                if (!includeReturnValueParameter)
                {
                    cmd.Parameters.RemoveAt(0);
                }
    
                // 创建参数数组   
                SqlParameter[] discoveredParameters = new SqlParameter[cmd.Parameters.Count];
                // 将cmd的Parameters参数集复制到discoveredParameters数组.   
                cmd.Parameters.CopyTo(discoveredParameters, 0);
    
                // 初始化参数值为 DBNull.Value.   
                foreach (SqlParameter discoveredParameter in discoveredParameters)
                {
                    discoveredParameter.Value = DBNull.Value;
                }
                return discoveredParameters;
            }
    
            /// <summary>   
            /// SqlParameter参数数组的深层拷贝.   
            /// </summary>   
            /// <param name="originalParameters">原始参数数组</param>   
            /// <returns>返回一个同样的参数数组</returns>   
            private static SqlParameter[] CloneParameters(SqlParameter[] originalParameters)
            {
                SqlParameter[] clonedParameters = new SqlParameter[originalParameters.Length];
    
                for (int i = 0, j = originalParameters.Length; i < j; i++)
                {
                    clonedParameters[i] = (SqlParameter)((ICloneable)originalParameters[i]).Clone();
                }
    
                return clonedParameters;
            }
    
            #endregion 私有方法,字段,构造函数结束
    
            #region 缓存方法
    
            /// <summary>   
            /// 追加参数数组到缓存.   
            /// </summary>   
            /// <param name="connectionString">一个有效的数据库连接字符串</param>   
            /// <param name="commandText">存储过程名或SQL语句</param>   
            /// <param name="commandParameters">要缓存的参数数组</param>   
            public static void CacheParameterSet(string connectionString, string commandText, params SqlParameter[] commandParameters)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
    
                string hashKey = connectionString + ":" + commandText;
    
                paramCache[hashKey] = commandParameters;
            }
    
            /// <summary>   
            /// 从缓存中获取参数数组.   
            /// </summary>   
            /// <param name="connectionString">一个有效的数据库连接字符</param>   
            /// <param name="commandText">存储过程名或SQL语句</param>   
            /// <returns>参数数组</returns>   
            public static SqlParameter[] GetCachedParameterSet(string connectionString, string commandText)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
    
                string hashKey = connectionString + ":" + commandText;
    
                SqlParameter[] cachedParameters = paramCache[hashKey] as SqlParameter[];
                if (cachedParameters == null)
                {
                    return null;
                }
                else
                {
                    return CloneParameters(cachedParameters);
                }
            }
    
            #endregion 缓存方法结束
    
            #region 检索指定的存储过程的参数集
    
            /// <summary>   
            /// 返回指定的存储过程的参数集   
            /// </summary>   
            /// <remarks>   
            /// 这个方法将查询数据库,并将信息存储到缓存.   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符</param>   
            /// <param name="spName">存储过程名</param>   
            /// <returns>返回SqlParameter参数数组</returns>   
            public static SqlParameter[] GetSpParameterSet(string connectionString, string spName)
            {
                return GetSpParameterSet(connectionString, spName, false);
            }
    
            /// <summary>   
            /// 返回指定的存储过程的参数集   
            /// </summary>   
            /// <remarks>   
            /// 这个方法将查询数据库,并将信息存储到缓存.   
            /// </remarks>   
            /// <param name="connectionString">一个有效的数据库连接字符.</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="includeReturnValueParameter">是否包含返回值参数</param>   
            /// <returns>返回SqlParameter参数数组</returns>   
            public static SqlParameter[] GetSpParameterSet(string connectionString, string spName, bool includeReturnValueParameter)
            {
                if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    return GetSpParameterSetInternal(connection, spName, includeReturnValueParameter);
                }
            }
    
            /// <summary>   
            /// [内部]返回指定的存储过程的参数集(使用连接对象).   
            /// </summary>   
            /// <remarks>   
            /// 这个方法将查询数据库,并将信息存储到缓存.   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接字符</param>   
            /// <param name="spName">存储过程名</param>   
            /// <returns>返回SqlParameter参数数组</returns>   
            internal static SqlParameter[] GetSpParameterSet(SqlConnection connection, string spName)
            {
                return GetSpParameterSet(connection, spName, false);
            }
    
            /// <summary>   
            /// [内部]返回指定的存储过程的参数集(使用连接对象)   
            /// </summary>   
            /// <remarks>   
            /// 这个方法将查询数据库,并将信息存储到缓存.   
            /// </remarks>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="includeReturnValueParameter">   
            /// 是否包含返回值参数   
            /// </param>   
            /// <returns>返回SqlParameter参数数组</returns>   
            internal static SqlParameter[] GetSpParameterSet(SqlConnection connection, string spName, bool includeReturnValueParameter)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                using (SqlConnection clonedConnection = (SqlConnection)((ICloneable)connection).Clone())
                {
                    return GetSpParameterSetInternal(clonedConnection, spName, includeReturnValueParameter);
                }
            }
    
            /// <summary>   
            /// [私有]返回指定的存储过程的参数集(使用连接对象)   
            /// </summary>   
            /// <param name="connection">一个有效的数据库连接对象</param>   
            /// <param name="spName">存储过程名</param>   
            /// <param name="includeReturnValueParameter">是否包含返回值参数</param>   
            /// <returns>返回SqlParameter参数数组</returns>   
            private static SqlParameter[] GetSpParameterSetInternal(SqlConnection connection, string spName, bool includeReturnValueParameter)
            {
                if (connection == null) throw new ArgumentNullException("connection");
                if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
    
                string hashKey = connection.ConnectionString + ":" + spName + (includeReturnValueParameter ? ":include ReturnValue Parameter" : "");
    
                SqlParameter[] cachedParameters;
    
                cachedParameters = paramCache[hashKey] as SqlParameter[];
                if (cachedParameters == null)
                {
                    SqlParameter[] spParameters = DiscoverSpParameterSet(connection, spName, includeReturnValueParameter);
                    paramCache[hashKey] = spParameters;
                    cachedParameters = spParameters;
                }
    
                return CloneParameters(cachedParameters);
            }
    
            #endregion 参数集检索结束
    
        }
    }
    View Code

     2、ConvertJson类

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WindowsFormsApplication_1709
    {
        /// <summary>
        /// DataTable 转换成Json 操作类
        /// </summary>
        public static class ConvertJson
        {
            #region  DataSet转换为Json
    
            /// <summary>           
            /// DataSet转换为Json     
            /// </summary>       
            /// <param name="dataSet">DataSet对象</param>
            /// <returns>Json字符串</returns>  
            public static string ToJson(DataSet dataSet)
            {
                string jsonString = "{";
                foreach (DataTable table in dataSet.Tables)
                {
                    jsonString += """ + table.TableName + "":" + ToJson(table) + ",";
                }
                jsonString = jsonString.TrimEnd(',');
                return jsonString + "}";
            }
            #endregion
    
            #region Datatable转换为Json
    
            /// <summary>   
            /// Datatable转换为Json 
            /// </summary>      
            /// <param name="table">Datatable对象</param>
            /// <returns>Json字符串</returns>    
            public static string ToJson(DataTable dt)
            {
                StringBuilder jsonString = new StringBuilder();
                jsonString.Append("[");
                DataRowCollection drc = dt.Rows;
                for (int i = 0; i < drc.Count; i++)
                {
                    jsonString.Append("{");
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        string strKey = dt.Columns[j].ColumnName;
                        string strValue = drc[i][j].ToString();
                        Type type = dt.Columns[j].DataType;
                        jsonString.Append(""" + strKey + "":");
                        strValue = StringFormat(strValue, type);
                        if (j < dt.Columns.Count - 1)
                        {
                            jsonString.Append(strValue + ",");
                        }
                        else
                        {
                            jsonString.Append(strValue);
                        }
                    }
                    jsonString.Append("},");
                }
                jsonString.Remove(jsonString.Length - 1, 1);
                jsonString.Append("]");
                return jsonString.ToString();
            }
    
            /// <summary>  
            /// DataTable转换为Json 
            /// </summary>    
            public static string ToJson(DataTable dt, string jsonName)
            {
                StringBuilder Json = new StringBuilder();
                if (string.IsNullOrEmpty(jsonName))
                    jsonName = dt.TableName;
                Json.Append("{"" + jsonName + "":[");
                if (dt.Rows.Count > 0)
                {
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {
                        Json.Append("{");
                        for (int j = 0; j < dt.Columns.Count; j++)
                        {
                            Type type = dt.Rows[i][j].GetType();
                            Json.Append(""" + dt.Columns[j].ColumnName.ToString() + "":" + StringFormat(dt.Rows[i][j].ToString(), type));
                            if (j < dt.Columns.Count - 1)
                            {
                                Json.Append(",");
                            }
                        }
                        Json.Append("}");
                        if (i < dt.Rows.Count - 1)
                        {
                            Json.Append(",");
                        }
                    }
                }
                Json.Append("]}");
                return Json.ToString();
            }
    
            #endregion
    
            /// <summary>     
            /// 格式化字符型、日期型、布尔型 
            /// </summary>     
            /// <param name="str"></param>   
            /// <param name="type"></param> 
            /// <returns></returns>     
            private static string StringFormat(string str, Type type)
            {
                if (type == typeof(string))
                {
                    str = String2Json(str);
                    str = """ + str + """;
                }
                else if (type == typeof(DateTime))
                {
                    str = """ + str + """;
                }
                else if (type == typeof(bool))
                {
                    str = str.ToLower();
                }
                else if (type != typeof(string) && string.IsNullOrEmpty(str))
                {
                    str = """ + str + """;
                }
                return str;
            }
    
            #region 私有方法
            /// <summary>     
            /// 过滤特殊字符    
            /// </summary>    
            /// <param name="s">字符串</param> 
            /// <returns>json字符串</returns> 
            private static string String2Json(String s)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < s.Length; i++)
                {
                    char c = s.ToCharArray()[i];
                    switch (c)
                    {
                        case '"':
                            sb.Append("\""); break;
                        case '\':
                            sb.Append("\\"); break;
                        case '/':
                            sb.Append("\/"); break;
                        case '':
                            sb.Append("\b"); break;
                        case 'f':
                            sb.Append("\f"); break;
                        case '
    ':
                            sb.Append("\n"); break;
                        case '
    ':
                            sb.Append("\r"); break;
                        case '	':
                            sb.Append("\t"); break;
                        default:
                            sb.Append(c); break;
                    }
                }
                return sb.ToString();
            }
            #endregion
        }
    }
    View Code
  • 相关阅读:
    openwrt 相关文章
    负载均衡相关文章
    Today's Progress
    Rodrigues formula is beautiful, but uneven to sine and cosine. (zz Berkeley's Page)
    Camera Calibration in detail
    Fundamental Matrix in Epipolar
    Camera Calibration's fx and fy do Cares in SLAM
    FilterEngine::apply
    FilterEngine 类解析——OpenCV图像滤波核心引擎(zz)
    gaussBlur
  • 原文地址:https://www.cnblogs.com/luna-hehe/p/9117861.html
Copyright © 2011-2022 走看看