在这个例子中,我们调用`ExecuteSQLStatement`直接执行了一个SQL查询,但思想跟`ExecuteStoredProcedure`是一样的。
  我们使用`resultDataReader`的`.Read()`方法来迭代处理返回的结果集。另外提供了一些helper方法来避免叠代中由于NULL字段、GetIntValueOfDBField等引起的异常。
  如果你要执行SQL命令而不是存储过程,需要传入ExecuteSQLStatement的userData有三类:
  ReaderQueryCallbackResult userData;
  适用于有返回recordset的语句,可以通过userData.resultDataReader获得对返回的recordset的访问。
  NonQueryCallbackResult userData
  适用于像UPDATE这种没有返回内容的语句,可以使用userData.AffectedRows检查执行的结果。
  ScalarQueryCallbackResult userData
  用于查询语句只返回一个标量值的情况,例如`SELECT code FROM tbl WHEN ID=10`,通过userData.ScalarValue取得返回的结果。
  对于存储过程,只有一种需要传入ExecuteStoredProcedure的数据类型。但在声明变量时你需要指明存储过程的返回值类型:
  StoredProcedureCallbackResult userData(eRequestType)
  除了声明不同外,其他操作与上面相同。
  异步地使用代码
  假使你不希望调用线程被查询阻塞,你需要周期性地调用`WaitSqlCompletes`来检查查询是否完成,执行是否失败。
  ///<summary>
  ///你需要周期性地调用WaitSqlCompletes(userData,10)
  ///来查看结果是否可用!
  ///</summary>
  public StoredProcedureCallbackResult MyStoreProcedureASYNC(int param1,string param2)
  {
  //Create user data according to return type of store procedure in SQL
  StoredProcedureCallbackResult userData=new StoredProcedureCallbackResult(eRequestType.Reader);
  //If your store procedure accepts some parameters,define them here,
  //or you can omit it incase there is no parameter definition
  userData.Parameters=new System.Data.SqlClient.SqlParameter[]{
  new System.Data.SqlClient.SqlParameter("@param1",param1),
  new System.Data.SqlClient.SqlParameter("@param2",param2),
  };
  //Execute procedure...
  if(!ExecuteStoredProcedure("usp_MyStoreProcedure",userData))
  throw new Exception("Execution failed");
  return userData;
  }
  在调用线程中你需要这样做:
  ...
  DAL.StoredProcedureCallbackResult userData=myDal.MyStoreProcedureASYNC(10,"hello");
  ...
  //each time we wait 10 milliseconds to see the result...
  switch(myDal.WaitSqlCompletes(userData,10))
  {
  case eWaitForSQLResult.Waiting:
  goto WAIT_MORE;
  case eWaitForSQLResult.Success:
  goto GET_THE_RESULT;
  default:
  goto EXECUTION_FAILED;
  }
  ...
  数据库状态
  在BLL中只有一个异步地提供数据库状态的事件。如果数据库连接被断开了(通常是由于网络问题),OnDatabaseStatusChanged事件会被挂起。
  另外,如果连接恢复了,这个事件会被再次挂起来通知你新的数据库状态。
  有趣的地方
  在我开发代码的时候,我明白了连接字符串中的连接时限(connection timeout)和SQL命令对象的执行时限(execution timeout)同样重要。
  首先,你必须意识到大容许时限是在连接字符串中定义的,并可以给出一些执行指令比连接字符串中的超时时间更长的时间。
  其次,每一个命令都有着它们自己的执行时限,在这里的代码中默认为30秒。你可以很容易地修改它,使它适用于所有类型的命令,像这样:
  userData.tsWaitForResult=TimeSpan.FromSeconds(15);