0

あるテーブルからレコードのリストを取得し、別のテーブルに書き込もうとしています。簡単なクエリを使用して値を SqlDataReader に取得し、それらを DataTable にロードしました。DataTableReader を使用して、DataTable に保存されているデータ セット全体を調べています。問題は、すべてのレコードを読み取っているときに、ストアドプロシージャを使用してそれらの値を別のテーブルに挿入しようとしていることです。「プロシージャまたは関数に指定された引数が多すぎます」 .


string ConStr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
SqlConnection NewCon = new SqlConnection(ConStr);
NewCon.Open();

SqlCommand NewCmd3 = NewCon.CreateCommand();
NewCmd3.CommandType = CommandType.Text;
NewCmd3.CommandText ="select * from dbo.Request_List where  group_no ='" +group_no+      "'";
NewCon.Close();
NewCon.Open(); 
SqlDataReader dr = (SqlDataReader)NewCmd3.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
DataTableReader reader = new DataTableReader(dt);

NewCmd.Dispose();
NewCon.Close();
NewCon.Open();

SqlCommand NewCmdGrpReqSer = NewCon.CreateCommand();
NewCmdGrpReqSer.CommandType = CommandType.StoredProcedure;
NewCmdGrpReqSer.CommandText = "Voucher_Request_Connection";
if (reader.HasRows)
{
    int request_no = 0;
    while (reader.Read())
    {
        request_no = (int)reader["request_no"];
        NewCmdGrpReqSer.Parameters.Add("@serial_no", serial_no);
        NewCmdGrpReqSer.Parameters.Add("@request_no", request_no);
        try
        {
            NewCmdGrpReqSer.ExecuteNonQuery();
            MessageBox.Show("Connection Updated");//just to check the status.tempory 
        }
        catch (Exception xcep)
        {
            MessageBox.Show(xcep.Message);
        }
        MessageBox.Show(request_no.ToString());// 
    }
    NewCmdGrpReqSer.Dispose();
    NewCon.Close();
}

解決策はありますか?

4

2 に答える 2

3

@Sparky が示唆するように、問題は挿入コマンドにパラメーターを追加し続けることです。ただし、コードを改善する方法は他にもいくつかあります。これらの改善により、パラメーターをクリアする必要がなくなり、使い捨てのリソースを未処理のままにしないようにするのに役立ちます。

まず - を使用しますusing使い捨てオブジェクトのステートメント。これにより、明示的な Close の必要がなくなります (ちなみに、Dispose が Close を呼び出すと信じているため、接続には Close/Dispose の 1 つだけが必要です)。次に、挿入ごとに新しいコマンドを作成します。これにより、パラメーターのリセットや、場合によってはコマンドのエラー状態の処理に関する複雑なロジックが回避されます。3 番目に、挿入の結果をチェックして、成功したことを確認します。第 4 に、SqlException を明示的にキャッチします。予期しないエラーを誤ってコードに隠してしまうことは望ましくありません。すべての例外がバブルアップしないようにする必要がある場合は、複数の例外ハンドラーを使用し、ケースごとに「正しいことを行う」ことを検討してください。たとえば、さまざまなエラーレベルまたはカテゴリでログを記録し、この挿入だけではなく操作全体を中止するなどです。 . 最後に、より良い変数名を使用します。特に、汎用変数名に数値識別子を追加することは避けてください。これにより、コードをしばらく放置すると、他の人にとっても自分自身にとっても、コードが理解しにくくなります。

これが私のバージョンです。文字列リテラルを適切な名前の定数にするなど、他にもいくつかのことができることに注意してください。テストを容易にするために、ConfigurationManager オブジェクトに厳密に型指定されたラッパーを導入します。変数名からアンダースコアを削除し、代わりにキャメルケースを使用してください。それらは本質的により文体的ですが、それらも考慮したい場合があります.

var connectionString = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
using (var newConnection = new SqlConnection(connectionString))
{
    newConnection.Open();

    using (var selectCommand = newConnection.CreateCommand())
    {
        selectCommand.CommandType = CommandType.Text;
        select.CommandText ="select request_no from dbo.Request_List where group_no = @groupNumber";
        selectCommand.Parameters.AddWithValue("groupNumber", group_no);

        using (dataReader = (SqlDataReader)newCommand.ExecuteReader())
        {
            while (reader.HasRows && reader.Read())
            {
                using (var insertCommand = newConnection.CreateCommand())
                {
                    insertCommand.CommandType = CommandType.StoredProcedure;
                    insertCommand.CommandText = "Voucher_Request_Connection";

                    var request_no = (int)reader["request_no"];
                    insertCommand.Parameters.Add("@serial_no", serial_no);
                    insertCommand.Parameters.Add("@request_no", request_no);
                    try
                    {
                         if (insertCommand.ExecuteNonQuery() == 1)
                         {
                             MessageBox.Show("Connection Updated");//just to check the status.tempory 
                         }
                         else
                         {
                             MessageBox.Show("Connection was not updated " + request_no);
                         }
                    }
                    catch (SqlException xcep)
                    {
                        MessageBox.Show(xcep.Message);
                    }
                    MessageBox.Show(request_no.ToString());// 
                }
            }
        }
    }
}
于 2013-09-02T16:58:22.593 に答える