2011-12-21 19 views
2

データベースアプリケーションを設計しており、データベースのデータを取り込むフォームを持っています。ユーザーがフォーム上のテキストボックスをダブルクリックすると、入力ボックスを使用して値を変更できます。入力ボックスでは、次のコードを実行してデータベースを更新します。SqlCommand.ExecuteNonQuery()はデータベースを更新しません。

private void ProcessChanges(string strField, string strCurrentValue) 
    { 
     //...Connect To Database...// 

     string strCaseNo = txtCaseNo.Text; 
     string strConnect = BuildConnectionString(); 
     SqlConnection linkToDB = new SqlConnection(strConnect); 
     linkToDB.Open(); 

     //...Request User Input New Value...// 

     string strMessage = "Enter ammended details and click OK," + Environment.NewLine + 
           "or click Cancel to exit."; 
     string strInput = Interaction.InputBox(strMessage, "Case Details", strCurrentValue); 

     //...Send User Input to Database...// 

     string commandText = "UPDATE tblCases SET @FieldVal = @InputVal WHERE CaseNo = @CaseNoVal;"; 
     SqlCommand sqlCom = new SqlCommand(commandText, linkToDB); 
     sqlCom.Parameters.Add("@FieldVal", SqlDbType.Text); 
     sqlCom.Parameters.Add("@InputVal", SqlDbType.Text); 
     sqlCom.Parameters.Add("@CaseNoVal", SqlDbType.VarChar); 
     sqlCom.Parameters["@FieldVal"].Value = strField; 
     sqlCom.Parameters["@InputVal"].Value = strInput; 
     sqlCom.Parameters["@CaseNoVal"].Value = strCaseNo; 
     int intQuery = sqlCom.ExecuteNonQuery(); 
     MessageBox.Show(intQuery.ToString()); 
    } 

問題は、データベースがまったく更新されないことです。私は同じConnectionStringBuilderが私のアプリ全体で使用されているので、接続がOKであることを知っています。私は最後にExecuteNonQuery()の戻り値が '1'であることを伝えるメッセージボックスを追加しました。これは、行が更新されたことを示唆しています。しかし、私のデータベースでは何も変わりません。

+0

これはばかげた質問ですが、データベースが更新されていないことを100%確信していれば、キャッシュされた値を見ているかもしれませんか? – KingCronus

答えて

7

列名に変数を使用することはできません。文字列に列名が埋め込まれたSQL文字列を作成する必要があります。

string commandText = 
    "UPDATE tblCases SET [" + strField + "] = @InputVal WHERE CaseNo = @CaseNoVal;" 

ただし、SQLインジェクション攻撃の場合はstrFieldの値をチェックする必要があります。

+1

+1 OPのコードは、変数の割り当てを終えるだけで、何も更新しません。 –

+0

@MartinSmith:しかし、それは種類のSQLエラーを与えるべきではありません:*変数はデカールされていません*? – Jan

+0

名前のパラメータを渡しているため、いいえ。私は上記のパラメータの割り当てを述べたはずです。 –

0

@ヤンがあります。しかし、さておきとして、あなたは本当には廃棄されなければならないまたはMSDNから、あなたのSqlConnectionを閉じる:SqlConnectionオブジェクトがスコープの外に出る

場合は、それが閉じられません。したがって、CloseまたはDisposeを呼び出すことによって明示的に接続を閉じる必要があります。 CloseとDisposeは機能的に同等です。接続プーリング値Poolingがtrueまたはyesに設定されている場合、基礎となる接続は接続プールに戻されます。一方、Poolingがfalseまたはnoに設定されている場合、サーバーへの基礎接続は実際に閉じられます。

using構築物は、単にそのようなことのためにC#で存在している:あなたは、次のようにCommandTextを行を更新した場合

using (SqlConnection linkToDB = new SqlConnection(strConnect) 
{ 
    // use the linkToDb here 
} 
1

string commandText = "UPDATE tblCases SET @FieldVal = " + strField + " WHERE CaseNo = @CaseNoVal;"; 

をし、ラインに

sqlCom.Parameters.Add("@FieldVal", SqlDbType.Text); 
sqlCom.Parameters["@FieldVal"].Value = strField; 
を削除

でも、doこれは潜在的にSQLインジェクション攻撃につながる可能性があるので、このメソッドに提供されている値を本当に信頼するか、strFieldの値に実際のSQL文が含まれていないことを確認する必要があります。

strFieldに;[some malicious SQL here]が含まれている場合、これは接続に割り当てられたユーザーの権限で実行されます。

+0

警告をありがとう - 私はそれについて考えていません。しかし、この特定のアプリケーションでは、ユーザーはフィールド名にアクセスできません。フィールド名(strfield)は、ProcessChanges()を呼び出すコントロールによって送信されます。 – PJW

関連する問題