- PR -

Oracle:TimeStampと.NET:DateTimeの比較について

投稿者投稿内容
当主
会議室デビュー日: 2006/12/10
投稿数: 16
投稿日時: 2007-10-26 13:42
お世話になっております、当主です。


件名の件で質問がありましたので投稿させていただきました。
現在WEBアプリ製作中であり、TimeStampでの楽観排他を実装しようとしています。


表示のためにデータ取得した際に、DateTime型の変数に値を保存しておき、
登録(更新)ボタンが押された際にDataTableに値を設定してDbDataAdapterから更新・追加を
しようとしています。
その際、UPDATEのWHERE句で比較をしているのですが、どうにも同じものと判断されずに
DBConcurrencyExceptionが発生します。


OracleDBから.NETのDateTimeに値をとってきた際には、DateTime型変数にはミリ秒3桁までちゃんと
設定されているのですが、それをそのまま引数にして比較をしてやってもうまくいきません。
仮に比較などをせずに、DateTime型変数のものをTimeStamp型のカラムに登録してやると、
ミリ秒が切り捨てられるようです。

データセットからUpdateQueryでUpdateすると確かミリ秒まで入った気がしますが、
DbDataAdapterからテーブルごと送ってやると反映されません。


ミリ秒の桁数などで何かコツなどがあるのでしょうか。
アドバイス等よろしくお願いいたします。



:再編集
解決したと言うのが手違いでした。
一度は登録がうまくいくように見えたのですが、またエラーが発生し、成功時の状態が
再現できません。
私の勘違いだったようです。
上記の通り、アドバイスお待ちしております。



[ メッセージ編集済み 編集者: 当主 編集日時 2007-10-26 15:12 ]

[ メッセージ編集済み 編集者: 当主 編集日時 2007-10-26 15:59 ]
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-10-26 16:33
未検証なのですが、プロバイダは何を使用していますか?
このあたりを見ると

http://www.microsoft.com/japan/msdn/net/general/odpvsmsdp.aspx
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/win.102/B25804-01/using.htm

TimeStamp → DateTime だと値がうまくとれなそうな気がします。
OracleTimeStamp 構造体を使ってみてはどうでしょうか?
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/win.102/B31247-01/OracleTimeStampStructure.htm#i1013405

_________________
かるあ のメモスニペット
deanna
大ベテラン
会議室デビュー日: 2004/08/23
投稿数: 118
投稿日時: 2007-10-26 16:46
OracleのTimeStampを文字列にして扱えばいいのでは。
SELECT TO_CHAR(xx,'YYYYMMDDHH24MISSFF3') FROM ...
とか
当主
会議室デビュー日: 2006/12/10
投稿数: 16
投稿日時: 2007-10-26 17:00
かるあ様

アドバイスありがとうございます。
プロバイダはMicrosoftプロバイダ(System.Data.OracleClient)を使用しています。
Oracleから取得の際にはミリ秒も取得できていますので、問題の本筋はDbDataAdapterの
UpdateCommandでミリ秒が切り捨てられている部分の気がします。


deanna様

アドバイスありがとうございます。
取得時にはミリ秒も取れていますし、データテーブルに設定する際には
DateTime型のものを設定しないといけないので解決にはならない気がします。
TimeStampにはSYSTIMESTAMPで自動設定したいと考えてもおりますし。


[ メッセージ編集済み 編集者: 当主 編集日時 2007-10-26 17:48 ]
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-10-26 17:18
引用:

当主さんの書き込み (2007-10-26 17:00) より:

アドバイスありがとうございます。
プロバイダはMicrosoftプロバイダ(System.Data.OracleClient)を使用しています。
Oracleから取得の際にはミリ秒も取得できていますので、問題の本筋はDbDataAdapterの
UpdateCommandでミリ秒が切り捨てられている部分の気がします。


TimeStamp の値がとれているとのことですが、どこまでとれていますか?
また、先ほどのリンクで 秒の端数 の項目にあったと思いますが、Oracle 側の TimeStamp の精度はどうなっていますか?

_________________
かるあ のメモスニペット
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2007-10-26 17:28
ググってきました!いろいろ回避方法はありそうです。

OracleDataAdapterの安全な型マッピング
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/win.102/B31247-01/featSafeType.htm

.NET Framework クラス ライブラリ
OracleDateTime 構造体
http://msdn2.microsoft.com/ja-jp/library/system.data.oracleclient.oracledatetime(VS.80).aspx
当主
会議室デビュー日: 2006/12/10
投稿数: 16
投稿日時: 2007-10-26 17:42
かるあ様

TimeStamp→DateTimeで値を確認すると、ミリ秒3桁までです。
DB側にマイクロ秒まで格納されていても、取得される値はミリ秒まででした。

それからOracleの精度ですが、何も設定をしていないのでおそらくデフォルトの6桁だと思われます。
そのあたりがいまいち把握できておらず、またどこを見て確認・設定すればいいのか
皆目検討がつきません。


Anthyhime様

アドバイスありがとうございます。
もちろん私もググりましたが、よくわかりませんでした。
安全なマッピングの言いたいことはわかりますが、その実装方法が理解できませんでしたし、
OracleDateTimeに関しては、結局その型で取得してもDataTableに設定する際には
DateTimeにしなくてはいけないので意味が無いように思います。


ちなみにDataAdapter.Updateだとこれまで言っているとおりミリ秒が無視されますが、
データセットを作成してUpdateQueryを使うとミリ秒は入ります。
そもそも前提として勘違いしているのでしょうか…?

[ メッセージ編集済み 編集者: 当主 編集日時 2007-10-26 18:03 ]
ひろ
会議室デビュー日: 2007/09/19
投稿数: 9
投稿日時: 2007-10-29 09:47
更新時、テーブルに登録されている TIMESTAMP カラムをキーに更新しに行くと
精度の問題で一致しないということですよね?

読み込んできたデータセット内で、ミリ秒の精度があるようですので、
更新 SQL の WHERE 句で、テーブルの TIMESTAMP の値を文字列変換して比較
すればいいのでは?

------------------------------------------------------------

UPDATE …
WHERE
TO_CHAR([UPDDATE],[FORMAT]) = '[TARGET]'

UPDDATE:更新対象のTIMESTAMPカラム名
FORMAT :比較する書式フォーマット(例:YYYYMMDDHHMISSFF3 )
TARGET :DataSetの更新行の日付を文字列フォーマットしたもの

------------------------------------------------------------

ただ、これでも精度的に一致してしまう行が複数あるとだめですね。

#当主さんの立場や環境がわからないので何とも言えませんが、更新のキーに日付関連
項目を使用するのはあまり好ましくないと思われます。
やはり、そのテーブルのプライマリーキーで更新するのがいいのかな、と。
プライマリキーが無ければシーケンスでも用意して作成するのがよさげ。
もちろん、「プライマリーキーが存在しない」とか、「テーブルの仕様は変更不可」
など制約があるのかもしれませんが、その辺りの事は私たちには判らないです。

スキルアップ/キャリアアップ(JOB@IT)