2

私は、アクセス データベースから文字列フィールドを取得し、日付から名前 (姓名) を分離し、名前を日付とは別に別のアクセス データベースに保存するプログラムを使用しています。

日付値の一部がnullであることを除いてすべて完了したので、SQLをパラメーター化する必要がありますが、パラメーター化を機能させる方法を理解できませんでした。

変数にダミー値を入力したところ、それらがテーブルに正常に追加されました。以下のコード スニペットの他の変数は、すべて同じものを繰り返しているため、省略しています。os は、構造体からのデータを保持するリストです。

string sqlcmd = "INSERT INTO signatures VALUES ('" + os.QASignature + "', 'QADate = @QADATE'";
System.Data.OleDb.OleDbCommand SQLCommand = new System.Data.OleDb.OleDbCommand(sqlcmd, Connection);
using (SQLCommand)
{
    SQLCommand.Parameters.Add("@QADATE", System.Data.OleDb.OleDbType.Date).Value = os.QADate;
    SQLDataReader = SQLCommand.ExecuteReader();
}
4

5 に答える 5

6

次のようなものが必要です。

string sqlcmd = "INSERT INTO signatures (QASignature, QADate) VALUES (?, ?)";
using (System.Data.OleDb.OleDbCommand SQLCommand = new System.Data.OleDb.OleDbCommand(sqlcmd, Connection))
{
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "QASignature", Value = os.QASignature, DbType = DbType.String});
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "QADATE", Value = os.QADate, DbType = DbType.DateTime});
    SQLCommand.ExecuteNonQuery(); //Use ExecuteReader or ExecuteScalar when you want to return something
} 

os.QADate が null 許容 (DateTime?またはSystem.Nullable<DateTime>) の場合、次のようにします。

if(os.QADate == null) //Could easily be os.QADate == DateTime.MinValue too, for example
{
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "@QADATE", Value = DBNull.Value, DbType = DbType.DateTime});
}
else{
    SQLCommand.Parameters.Add(new OleDbParameter() { Name = "@QADATE", Value = os.QADate, DbType = DbType.DateTime});
}

元の例のように、文字列の連結とパラメーターを混在させないでください。どちらか一方です。実際には、 SQL インジェクションを防ぎ、他の利点 (より簡単な入力や、一部の RDBMS ではパラメーター化されたクエリのパフォーマンスが向上するなど) を得るためには、単なるパラメーター化であるべきです。

また、OleDBCommand は名前付きパラメーターの恩恵を受けないことに注意してください。パラメーターは、SQL に表示される順序でクエリに追加する必要があります。これが、SQL クエリに 2 つの疑問符が含まれている理由です。これらは単なるプレースホルダーです。

于 2012-07-17T22:36:45.907 に答える
4

nullに「変換」する必要がありますDBNull.Value。それを達成する1つの方法は、QADateがnull可能なDateTime(つまりDateTime?)であると仮定すると、次のようになります。

... .Value = os.QADate ?? DBNull.Value;

?? null 合体演算子であること。

編集:両方のオペランドが同じ型であることを確認するために、実際にキャストする必要がある場合があります。

... .Value = (object)os.QADate ?? DBNull.Value;

また、QASignature のパラメーターを使用しませんか?? なぜその値を「インライン化」しているのですか? QASignature に何が含まれるかはわかりませんが、これによりSQL インジェクションに対して脆弱になります。

最後に、なぜ挿入にExecuteReader()を使用しているのですか? なぜExecuteNonQuery()を使用しないのですか?

于 2012-07-17T22:32:22.480 に答える
1

DateTime を null にすることはできません。値が初期化されていない場合は、DateTime.MinValue になります。このケースをテストし、文字列値にもパラメーターを使用する必要があります。

using System.Data.OleDb;
....

string sqlcmd = "INSERT INTO signatures VALUES (@QASignature, @QADATE)"; 
using(OleDbCommand SQLCommand = new OleDbCommand(sqlcmd, Connection))
{ 
    SQLCommand.Parameters.AddWithValue("@QASignature",  os.QASignature);
    SQLCommand.Parameters.Add("@QADATE", OleDbType.Date).Value = 
               (os.QADate == DateTime.MinValue 
               ? (object)DBNull.Value
               : (object)os.QADate); 
    SQLDataReader = SQLCommand.ExecuteNonQuery(); 
} 

ちなみにinsert文は通常、ExecuteNonQuery

于 2012-07-17T22:37:19.213 に答える
0

Nullable(of T)構造体の使用を検討してください。次に、ソースオブジェクトに実際に変数がある場合にのみ設定できます。それ以外の場合、値は Null に設定され、SQL パラメータに適切に渡されます。古い TableAdapter クラスと新しい EntityFramework オブジェクトの多くは、(T の) Nullable 構造でも機能します。

于 2012-07-17T22:35:30.220 に答える
0

DBNull.Valueを使用します。

SQLCommand.Parameters.Add("@QADATE", 
                          System.Data.OleDb.OleDbType.Date).Value = DBNull.Value;

補足として、OleDbParameterCollection.AddWithValueを使用すると、データ型が自動的に推測され、コードを短くすることができます。

SQLCommand.Parameters.AddWithValue("@QADATE", DBNull.Value);
于 2012-07-17T22:33:26.633 に答える