2012-04-24 3 views
6

SQL DateTimeをSqlステートメントで使用することについていくつかの質問がありますが、いずれも問題を解決していません。パラメータ化されたSQL文字列で.Net DateTimeを使用する適切な方法

private DataTable QueryByIdAndDate(string id, DateTime fdate, DateTime tdate) { 
    string query = "SELECT * FROM table WHERE ID = :id AND DATE_TIME BETWEEN :from AND :to" 
    DbCommand cmd = db.CreateCommand(); 
    cmd.CommandType = CommandType.Text; 
    cmd.CommandText = query; 

    DbParameter fromDate = CreateDateParameter(cmd, fdate); 
    fromDate.ParameterName = "from"; 
    DbParameter toDate = CreateDateParameter(cmd, tdate); 
    toDate.ParameterName = "to"; 
    DbParameter idParam = CreateStringParameter(cmd, id); 
    idParam.ParameterName = "id"; 

    cmd.Parameters.AddRange(new DbParameter[] { fromDate, toDate, idParam }); 
    return db.ExecuteQuery(cmd); 
} 

private DbParameter CreateDateParameter(DbCommand cmd, DateTime date) { 
    DbParameter param = cmd.CreateParameter(); 
    param.DbType = DbType.DateTime; 
    param.Direction = ParameterDirection.Input; 
    param.Value = date; 
    return param; 
} 

をしかし、それは正しく動作しません:

私は、Oracleデータベースを照会するには、次のコードを使用しています。そのようなコードを実行しようとすると: ORA-01847:

DataTable result = QueryByIdAndDate("12345", DateTime.Now, DateTime.Now.AddDays(1)); 

それは次のエラーを与える月の日が1月の最後の日

間でなければなりません。私はそれが関係していると仮定していますDateTimeのフォーマット方法はわかりますが、これを信頼できる方法で修正する適切な方法はわかりません。

+0

30日以内に30日間それを実行することはありませんか? –

+0

私がDateTime.NowとDateTime.Now.AddDays(1)を使って示した例では失敗しました。 – user12345613

+2

ドライバは名前付きパラメータを確実にサポートしていますか?位置によってそれらを使用しようとすると、 "終了"部分として "id"値を使用することになります。これは壊れる可能性があります。どのドライバーを使用していますか? –

答えて

10

それは、この場合のように見えます

(...コメントを1として)、パラメータの順序は、あなたが彼らに名を与えてくれたという事実にもかかわらず...重要。私はこれを期待していないだろう、それは多少壊れドライバの兆候だが、それにあなたのコードを変更:それを修正する必要があり

cmd.Parameters.AddRange(new DbParameter[] { idParam, fromDate, toDate }); 

。 (これは必ずしもあなたが道で、あなたのパラメータを構築しなければならない方法ではありませんが、それはここではやや軽微です。)

は文字列として、日付/時刻の値を指定し ないスタートを行います。 実際に悪い考えであるは、必要以上の文字列変換を導入しています。あなたが使用しようとしている場合

あなたがなどのパラメータ値をフォーマットする方法も重要ではありません:@JonSkeetによって受け入れ答えの下@kprobstによってコメントを参照してください、それを逃す可能性があるものについては

+0

はい私はその配列の順序について考えていませんでした。なぜなら、それらは名前付きのパラメータなので愚かでした。また、私は、パラメータを適切に構築する上での意見や提案があれば公開しています。 – user12345613

+0

私の経験では、oracleの.netドライバでは、パラメータの順序やNULL参照の例外を取り除くためにSQL文を変更する必要があるなど、多くの問題が発生しています。 –

+0

@ user12345613:これは私が多くの経験があるとは言えませんが、強く型付けされたコマンドパラメータコレクションを使用すると、「AddWithValue」のようなオプションが得られます。 –

3

がフォーマットされた日付文字列にDateTime値を変換します。あなたは、文字列値を送信しているにもかかわらず

private DbParameter CreateDateParameter(DbCommand cmd, DateTime date) 
{ 
    DbParameter param = cmd.CreateParameter(); 
    param.DbType = DbType.DateTime; 
    param.Direction = ParameterDirection.Input; 
    param.Value = date.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); 
    return param; 
} 

DbTypeはまだDateTimeに設定されているので、値が正しく変換する必要があります。

+0

これは実際に問題があったとしても、おそらく不変の文化を使いたいと思うかもしれませんし、間違いなく "hh"を " HH "となる。私は強くそのような変換を実行することに反対しています*。 –

+0

@JonSkeetによって何も得られません。合意し、私は書式の問題にまっすぐに飛び乗って、パラメータの順序は考慮しませんでした。あなたの提案ごとに更新されました。 – mgnoonan

2

Oracleでは、「DD-Mon-YYYY」形式の日付が必要であるため、基本的に日付値をそのようにフォーマットし、パラメータ値に割り当てる必要があります。

編集:最近のODPのバージョンでは、日付時刻のパラメータがより適切に処理されているようです。 ODPの最新バージョンでこの方法がうまく動作し、クエリを実行

DateTime dt = new DateTime(2012, 5, 21); 
cmd.Parameters.Add("some_date_param", dt); 

:日付/時刻の列の上にWHERE句の制約がある場合には例えば、これはうまく動作します。しかし、私は、日付/時刻の値をフォーマットされた文字列として渡して、Oracleがそれらを受け入れる必要のあるコードをたくさん持っています。

1

CommandBindByNameプロパティを設定せずに名前をバインドします。

(OracleプロバイダAPI全体は、IMHOの杭です)。

関連する問題