1

foreachコントロールを使用して文字列の配列をループし、各値を使用してデータベースに情報を挿入しようとしています。using句内でforeach変数を使用できない理由を誰かが理解するのを手伝ってもらえますか?

string[] ship_ids = ShipsInScope.Split('|');
foreach (string ship_id in ship_ids)
{
     using (SqlCommand InsertCommand = new SqlCommand("insert into PROJECT_SHIP (CR_Number, Ship_Id) VALUES (@CR_Number, @CCF_Number)", DBConn))
    {
         InsertCommand.Parameters.Add("@CR_Number", SqlDbType.NVarChar, 10).Value = CRNumber;
         InsertCommand.Parameters.Add("@Ship_Id", SqlDbType.NVarChar, 10).Value = Ship_Id;

         InsertCommand.ExecuteNonQuery();
         InsertCommand.Dispose();
    }
}
4

6 に答える 6

6

C#では大文字と小文字が区別されます。反復変数はですが、ループでship_id使用しようとしています。Ship_Id

理想的には、代わりに(および他の変数にも)C#の命名規則を使用します。

// Declared outside the method.
private const string InsertSql = 
    "insert into PROJECT_SHIP (CR_Number, Ship_Id) " +
    "VALUES (@CR_Number, @CCF_Number)";

...

string[] shipIds = ShipsInScope.Split('|');
foreach (string shipId in shipIds)
{
    using (SqlCommand command = new SqlCommand(InsertSql, connection))
    {
        command.Parameters.Add("@CR_Number", SqlDbType.NVarChar, 10)
                          .Value = crNumber; // Unclear what this means
        command.Parameters.Add("@Ship_Id", SqlDbType.NVarChar, 10)
                          .Value = shipId;
        command.ExecuteNonQuery();
    }
}

ノート:

  • 定数SQLをクラスレベルの定数に抽出しました。必須ではありませんが、物事を明確にする可能性があります。
  • すべての変数の名前camelCaseをアンダースコアなしに変更しました
  • StackOverflowの折り返し行-おそらくコードをそれほど折り返す必要はありません
  • の冗長な明示的呼び出しを削除しましたDisposeusingステートメントはすでにDisposeを呼び出しているため)
于 2012-01-16T13:05:52.920 に答える
3

Ship_idの代わりに使用していship_idます。C#では大文字と小文字が区別されます。

string[] ship_ids = ShipsInScope.Split('|');
foreach (string ship_id in ship_ids)
{
     using (SqlCommand InsertCommand = new SqlCommand("insert into PROJECT_SHIP (CR_Number, Ship_Id) VALUES (@CR_Number, @CCF_Number)", DBConn))
    {
         InsertCommand.Parameters.Add("@CR_Number", SqlDbType.NVarChar, 10).Value = CRNumber;
         InsertCommand.Parameters.Add("@Ship_Id", SqlDbType.NVarChar, 10).Value = ship_Id;

         InsertCommand.ExecuteNonQuery();
    }
}

さらに、usingブロックは最終的に呼び出しDisposeますInsertCommand-それはusingステートメントが行うことです。自分を呼ぶ必要はありませんDispose

于 2012-01-16T13:06:51.453 に答える
2

このステートメントを使用している場合はusing、メソッドを呼び出す必要はありません。Dispose()メソッドは内部的に呼び出され、パラメーターの名前は異なります。sqlステートメントでは@CCF_Number、パラメーターセクションでは@Ship_Idです。

于 2012-01-16T13:09:23.607 に答える
1

「ship_id」変数名を大文字にしました。

             InsertCommand.Parameters.Add("@Ship_Id", SqlDbType.NVarChar, 10).Value = Ship_Id
于 2012-01-16T13:07:17.710 に答える
1

これまでの回答とコメントに基づいて、次のようにコードを再構築できます。

const string sql = @"
    INSERT INTO PROJECT_SHIP (CR_Number, Ship_Id) 
    VALUES (@CR_Number, @Ship_Id)";

using (SqlCommand InsertCommand = new SqlCommand(sql, DBConn))
{
    var parameters = InsertCommand.Parameters;
    var crNumberParameter = parameters.Add("@CR_Number", SqlDbType.NVarChar, 10); 
    var shipIdParameter = parameters.Add("@Ship_Id", SqlDbType.NVarChar, 10);
    string[] ship_ids = ShipsInScope.Split('|');
    foreach (string ship_id in ship_ids)
    {
        crNumberParameter.Value = CRNumber;
        shipIdParameter.Value = ship_id;
        InsertCommand.ExecuteNonQuery();
    }
}
于 2012-01-16T13:25:13.053 に答える
0

別の注意点として、

非常に多くの操作で10000個の挿入コマンドをSQLServerに送信する代わりに

1回の操作でコレクション全体を追加するスクリプトを作成できる場合。

それがより効果的だと思います。

于 2012-01-16T13:18:45.100 に答える