none
byte型配列の比較 RRS feed

  • 質問

  • おはようございます。

    Vb2005+SQLServerExpressで開発しています。

    TimeStamp型のフィールドのデータをByte型の配列に格納しています。

    データを更新する際に、データを最初に取得した際のTimeStampを変数に格納して、更新実行時に再度主キーのデータの
    TimeStampを取得して、変数に取得したTimeStampとの比較を行い、異なる場合は警告を出すということを行おうと思っています。

    単純に
    変数1 Is 変数2

    でFalseがかえってくれば、それぞれの変数の値が異なるということで、更新済みのデータの有無を確認できると思ったのですが、
    デバッグで進めていき、「変数1」「変数2」を確認して、すべての配列のデータが同じことを確認しているのですが、
    上記の記述ではTrueがかえってきません。

    比較演算子を間違っているのでしょうか。

    どうか、よろしくお願いします。
    2009年6月26日 19:56

回答

  • 更新のストアドプロシージャを作成されているのであれば、そこで更新に成功すれば新しいTimeStamp値を返し、失敗すれば更新時に渡したTimeStamp値を返すようにします。
    プログラムでこのTimeStamp値と保存しておいたTimeStamp値を比較し、同じであれば更新に失敗していますし、異なっていれば更新に成功したと判断できます。
    成功すれば更新のストアドプロシージャから新しいTimeStamp値が返ってきていますので、それを前に保持していた値と置き換えて保持しておけば、続けて更新を行うことも可能です。

    更新に成功したかどうかはフラグなどで返してもいいんですが、どうせ新しいTimeStamp値を保持しなければならないのであれば、フラグなどを使わずTimeStamp値だけで比較する方法がスマートだと思います。

    #このレスを付ける位置を間違えてしまったようです。すみません。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/

    • 編集済み trapemiyaModerator 2009年6月29日 14:21 レスの付け先を間違えました。
    • 回答としてマーク TI-cb400 2009年7月6日 4:38
    2009年6月29日 5:02
    モデレータ

すべての返信

  • VS2008 のヘルプで「Is 演算子 (Visual Basic) 」を見ると、以下のように書いてあります。同じ
    オブジェクトでないから False になるのでは?

    "Is演算子は、2 つのオブジェクト参照が同じオブジェクトを参照しているかどうかを判定します。
    ただし、値の比較は行われません。"

    [追記]
    ちょっと調べてみましたが、C の memcmp のようなライブラリは見つかりませんでした。ループを
    まわして 1 バイトづつ比較していくのが一番簡単そうです。以下のページにその例が出ています。

    Visual Basic .NET を使用したハッシュ値の計算および比較方法
    http://support.microsoft.com/kb/301053/ja

    2009年6月26日 22:46
  • 更新実行時に再度主キーのデータのTimeStampを取得して、

    Byte配列の比較はSurferOnWwwさんが書かれている通りで良いのですが、更新時にTimeStampを取得するというのが気になりました。取得した直後に更新される可能性もあるからです。それとも更新ロックなどを使用されていますか? しかしこの方法だとユーザーが操作しないといつまでも更新ロックなどがかけられたままにならないように注意しなければなりません。
    やはり、.NETが同時実行制御の際に標準で生成するSQL文の考え方に従って、取得したTimeStamp値が変わっていないことを期待して更新しにいくのが簡単で確実だと思います。

    #蛇足だったかもしれません。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年6月27日 2:58
    モデレータ
  • ご回答ありがとうございます。

    データ型が違うとそもそも、比較自体が成り立たないのですね。
    勉強になりました。

    ループで1バイトずつ比較する方法を採用しております。

    自分が勉強不足なだけで恥ずかしい限りなのですが、現状では例えば登録ボタンを押したときに、データ取得の時点から
    データが更新されていた場合にエラーがだせるように、登録ボタンを押した時点で再度データ取得を行っております。

    データ更新のストアドプロシージャについては、検索キーにTimeStamp列を含んでおりますので、データの再取得
    直後に更新された場合は、データ更新自体が成功しないようにはしてあります。

    ただ、この際は、データ更新に失敗したということをどのように取得することができるのかがわからず、上記のような
    方法をとっています。

    2009年6月29日 4:09
  • 更新のストアドプロシージャを作成されているのであれば、そこで更新に成功すれば新しいTimeStamp値を返し、失敗すれば更新時に渡したTimeStamp値を返すようにします。
    プログラムでこのTimeStamp値と保存しておいたTimeStamp値を比較し、同じであれば更新に失敗していますし、異なっていれば更新に成功したと判断できます。
    成功すれば更新のストアドプロシージャから新しいTimeStamp値が返ってきていますので、それを前に保持していた値と置き換えて保持しておけば、続けて更新を行うことも可能です。

    更新に成功したかどうかはフラグなどで返してもいいんですが、どうせ新しいTimeStamp値を保持しなければならないのであれば、フラグなどを使わずTimeStamp値だけで比較する方法がスマートだと思います。

    #このレスを付ける位置を間違えてしまったようです。すみません。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/

    • 編集済み trapemiyaModerator 2009年6月29日 14:21 レスの付け先を間違えました。
    • 回答としてマーク TI-cb400 2009年7月6日 4:38
    2009年6月29日 5:02
    モデレータ
  • ご回答ありがとうございます。

    データの更新前に更新を行うことができるかどうか、チェックしたほうがよいと思って、上記のような段階を踏んでいたのですが、
    更新ができなければ、その時点で知らせるという方法をとればよかったのですね。

    今後とも、よろしくお願いいたします。
    2009年6月29日 11:55
  • > ただ、この際は、データ更新に失敗したということをどのように取得することができる
    > のかがわからず、上記のような方法をとっています。

    ストアドプロシージャを使っている理由は分かりませんが、それにこだわらないのであれば
    SqlDataSource と DetailsView などを組み合わせて、SqlDataSource.Updated イベントハン
    ドラで、その引数の SqlDataSourceStatusEventArgs オブジェクトの AffectedRows プロパ
    ティからデータベース操作の影響を受けた行の数を取得して、成功/不成功を判定するという
    のはいかがですか?

    Timestamp の処置がちょっと面倒ですが(Updating イベントハンドラで設定しなおすなどが
    必要)、それ以外はウィザードベースで簡単に実装できると思います。

    2009年6月29日 14:01