4

C# (.Net 2.0) でストアド プロシージャを呼び出さなければならない場合があります。ODBC 接続を使用する場合もあれば、SQLClient を使用する場合もあります。将来的には、Oracle とも通信する必要があるかもしれません。

私のストアド プロシージャには、入出力パラメータと戻り値があります。

CREATE PROCEDURE myProc (@MyInputArg varchar(10), @MyOutputArg varchar(20) output) AS (...) return @@ERROR

私の問題は、クライアントに関係なく一般的なコマンドを保存する方法が見つからないことです。IDbCommandオブジェクトを使用しています。

ODBC 接続では、次を定義する必要があります。

objCmd.CommandText = "? = CALL myProc (?,?)";

SQLclient コンテキストでは:

objCmd.CommandText = "myProc";

私は自分のコマンドを解析したくありません。一般的なコマンドを使用するためのより良い方法があると確信しています!

人々が再現できるようにするために、一般的なDB接続をどのように作成したかを以下に示します. 私のコンテキストでは、プロバイダー オブジェクトは構成ファイルから定義されます。

// My DB connection string, init is done from a configuration file
string myConnectionStr = "";

// Provider which defined the connection type, init from config file
//object objProvider = new OdbcConnection(); //ODBC
object objProvider = new SqlConnection(); // SQLClient

// My query -- must be adapted switch ODBC or SQLClient -- that's my problem!
//string myQuery = "? = CALL myProc (?,?)"; // ODBC
string myQuery = "myProc"; // SQLClient

// Prepare the connection
using (IDbConnection conn = (IDbConnection)Activator.CreateInstance(typeof(objProvider), myConnectionStr ))
{
    // Command creation
    IDbCommand objCmd = (IDbCommand)Activator.CreateInstance(typeof(objProvider));
    objCmd.Connection = conn;

    // Define the command
    objCmd.CommandType = CommandType.StoredProcedure;
    objCmd.CommandTimeout = 30;
    objCmd.CommandText = myQuery;

    IDbDataParameter param;

    // Return value
    param = (IDbDataParameter)Activator.CreateInstance(typeof(objProvider));
    param.ParameterName = "RETURN_VALUE";
    param.DbType = DbType.Int32;
    param.Direction = ParameterDirection.ReturnValue;
    objCmd.Parameters.Add(param);

    // Param 1 (input)
    param = (IDbDataParameter)Activator.CreateInstance(typeof(objProvider));
    param.ParameterName = "@MyInputArg";
    param.DbType = DbType.AnsiString;
    param.Size = 10;
    param.Direction = ParameterDirection.Input;
    param.Value = "myInputValue";
    objCmd.Parameters.Add(param);

    // Param 2 (output)
    param = (IDbDataParameter)Activator.CreateInstance(typeof(objProvider));
    param.ParameterName = "@MyOutputArg";
    param.DbType = DbType.AnsiString;
    param.Size = 20;
    param.Direction = ParameterDirection.Output;
    objCmd.Parameters.Add(param);

    // Open and execute the command
    objCmd.Connection.Open();
    objCmd.ExecuteReader(CommandBehavior.SingleResult);
    (...) // Treatment
}

御時間ありがとうございます。

よろしく、ティボー。

4

1 に答える 1

1

IDbCommand と実装の周りにラッパーを作成できます (ただし、必要な場合のみ:))。

//Note the IDisposable interface
public class MultiSqlCommand : IDisposable
{
  //DbConnectionType  is a custom enum
  public MultiSqlCommand(DbConnectionType connType, DbConnection conn)
  {
    //initialize members
    ...
    switch(connType) 
    {
      case ADO:
        _cmd = new SqlCommand(_connection);
        break;
      case ODBC:
        ...
    }
  }

  //As param name you pass the undecorated parameter name (no @, ?, etc.)
  public void AddParameter(string strippedName, object value) 
  {
    //this should be an internal function which gives you an SqlParameter formatted for your specific DbConnectionType
    object parameter = GetSqlParam(strippedName, value);
    _cmd.Parameters.Add(object);
  }
}

パラメータを追加すると、コマンドを実行する準備が整います。プロパティを介して公開し、このクラスの外部で実行するか、API を拡張していくつかのメソッドを追加して実行し、結果を得ることができます。便利だと思うものは何でも。

注: IDisposable の実装では、IDbCommand インスタンスを破棄する必要があります (null でない場合)。これは非常に重要です。そうしないと、メモリ リークが発生します。

提案が明確でない場合は、お知らせください。詳細を記入してみます。解決策は簡単です。さらに進んで、ADO.NET コマンドとパラメーターのサポート全体の上に抽象化レイヤーを作成することもできますが、ここでは本当に必要だとは思いません。データ プロバイダー全体を作成していないわけではありません。

于 2012-06-20T17:30:43.567 に答える