1

データベースに接続する次のコードがあります>ストアドプロシージャを実行し>次に進みます。

データベースプログラミングを間違えるのは簡単だと思うので、防御的であることが重要です。次は防御的ですか? (または改善できますか?)

public int RunStoredProc()
{
SqlConnection conn = null;
SqlCommand dataCommand = null;
SqlParameter param = null;
int myOutputValue;

try
{
    conn = new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString);                  
    conn.Open();
    dataCommand = conn.CreateCommand();
    dataCommand.CommandType = CommandType.StoredProcedure;
    dataCommand.CommandText = "pr_blahblah";
    dataCommand.CommandTimeout = 200; //seconds
    param = new SqlParameter();
    param = dataCommand.Parameters.Add("@NumRowsReturned", SqlDbType.Int);
    param.Direction = ParameterDirection.Output;
    dataCommand.ExecuteNonQuery();
    myOutputValue = (int)param.Value;

    return myOutputValue;
}
catch (SqlException ex)
{
    MessageBox.Show("Error:" + ex.Number.ToString(), "Error StoredProcedure");
    return 0;
}
finally
{
    if (conn != null)
    {
        conn.Close();
        conn.Dispose();
    }
}
}

コードは次のようになります

私は皆から提供されたすべてのヘルプを使用しようとしましたが、上記のコードは次のように修正されました。これで十分に防御できるようになりました。

public SqlConnection CreateConnection()
{
    SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString);
    return conn;
}
public int RunStoredProc()
{
    using (var conn = CreateConnection())
    using (var dataCommand = conn.CreateCommand()) 
    {
            conn.Open();
            dataCommand.CommandType = CommandType.StoredProcedure;
            dataCommand.CommandText = "pr_BankingChargebacks";
            dataCommand.CommandTimeout = 200; //5 minutes
            SqlParameter param = new SqlParameter();
            param = dataCommand.Parameters.Add("@NumRowsReturned", SqlDbType.Int);
            param.Direction = ParameterDirection.Output;
            dataCommand.ExecuteNonQuery();
            int myOutputValue = (int)param.Value;

            return myOutputValue;

    } 
}
4

5 に答える 5

7

usingそのようなもののための構文を使ってみてください。

using(var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString)
{
}

それができれば、あなたは適切な「防御」レベルに達していると思います。同様に、破棄する必要があるもの(コマンドなど)についても同じことを試みてください

于 2012-07-27T11:49:56.017 に答える
4
  • .Close()と の両方を呼び出す必要はありません。.Dispose()
  • using代わりにブロックを好むtry-finally
  • コマンド オブジェクトを破棄する
  • catch 句を削除します。ここには属していません (YMMV ですが)。

このコードをあちこちに書くつもりなら、やめてください。少なくともこれを行うには小さなヘルパー クラスを作成するか、 MassiveDapperPetaPocoなどの軽量の「ORM」を使用します。ADO.Net ヘルパー クラスの例については、https://github.com/jhgbrt/yadal/blob/master/Net.Code.ADONet.SingleFile/Db.csを参照してください。

于 2012-07-27T11:53:44.633 に答える
3

私が気付く主なことはMessageBox、データベースアクセスコードです。役に立つシナリオが 1 つも思い浮かびません。例外を発生させてください。それをキャッチしないでください。

一般的なテンプレートとして:

using(var conn = CreateConnection())
using(var cmd = conn.CreateCommand())
{
    // setup cmd and the parameters
    conn.Open();
    cmd.ExecuteNonQuery();
    // post-process cmd parameters (out/return/etc)
}

注: いいえClose()、いいえcatch; すべてfinallyによって処理されますusing。はるかに簡単です。間違いを犯すのははるかに困難です。

強調すべきもう 1 つの点は、接続を作成するためのファクトリ メソッドの使用です。入れないでください:

new SqlConnection(ConfigurationManager.ConnectionStrings["IMS"].ConnectionString)

すべてのメソッドに。結局...それは変わる可能性があり、不必要な繰り返しです.

于 2012-07-27T11:53:31.060 に答える
1

manojlds のアドバイスに加えて、データベースを呼び出すための再利用可能なヘルパー メソッドをいくつか作成することをお勧めします。たとえば、接続文字列を読み取り、接続を作成して開くメソッドを自分で作成します。どこでもインフラストラクチャのことを繰り返さないでください。

sproc またはコマンド テキストを呼び出す場合も同じことができます。

于 2012-07-27T11:53:19.733 に答える
1

例外を処理する方法である場合 MessageBox.Show("Error:" + ex.Number.ToString(), "Error StoredProcedure");、実際の例外の詳細をログに記録したり、取得したりすることさえありません。

于 2012-07-27T11:52:43.967 に答える