none
TimeStamp型を比較する方法 RRS feed

  • 質問

  • おはようございます。

    DBアプリケーションを作成中で、VB2005+SQLServer2005Expressという組み合わせで作成しております。

    レコードを更新する際に、今まではAccessを使用していたので、更新チェック用の列を用意しておき、その値を
    更新実行前に読み込んだときの内容と比較して、読み込んだときと同じ状態であるかを確認して更新しておりました。

    今回はSQLServerということで、TimeStamp型があるので、それを利用してみようと思うのですが、
    利用方法がわかりません。

    TimeStamp型の列の値をテキストボックスに入れておき、更新の際にその値と比較ができればと感得ています。

    問題は、
    1.TimeStamp型のデータをテキストボックスに格納できない
    バイナリデータなので、String型に変換しようと思い、以下のように記述をしたのですが、

    Dim TimeStampValue(7) As Byte

    TimeStampValue = CByte(DT.Rows(0)("pt_ts"))

    「型Byteの値をByteの一次元配列に変換できません」とエラーになります。

    いろいろと調べてはいるのですが、どうしたらよいかがわかりません。

    2.TimeStamp型を比較に用いるとき、テキストボックスに値を保持しておき、それを更新の際に比較をすると
    いう使い方が一般的なのか、それとも別の方法を用いて比較を行うのか。

    という点がわかりません。

    どうか、アドバイスお願いします。
    2009年3月13日 20:30

回答

  • TI-cb400さん の発言:

    問題は、
    1.TimeStamp型のデータをテキストボックスに格納できない
    バイナリデータなので、String型に変換しようと思い、以下のように記述をしたのですが、

    Dim TimeStampValue(7) As Byte

    TimeStampValue = CByte(DT.Rows(0)("pt_ts"))

    「型Byteの値をByteの一次元配列に変換できません」とエラーになります。

    いろいろと調べてはいるのですが、どうしたらよいかがわかりません。

    2.TimeStamp型を比較に用いるとき、テキストボックスに値を保持しておき、それを更新の際に比較をすると
    いう使い方が一般的なのか、それとも別の方法を用いて比較を行うのか。

    1.まず、TimeStampは8バイトですので、8バイトのバイト配列として定義して下さい。そのうえで、
    TimeStampValue = CType(DT.Rows(0)("pt_ts"), Byte())
    で良いと思います。

    2.テキストボックスに保存する必要はありません。8バイトのバイト配列に保存しておき、レコード更新時にその値を使って更新を行います。更新に失敗した場合は、誰か他の人が更新を行ったということですから、それをユーザーに知らせます。この辺りは楽観的同時実行制御の考え方と全く同じです。


     
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年3月15日 5:46
    • 回答としてマークされていない TI-cb400 2009年3月15日 6:15
    • 回答としてマーク sk7474 2009年4月2日 8:46
    2009年3月14日 8:22
    モデレータ
  • > 楽観的同時実行制御をしたいと思っています。
    >
    > 初めは、「更新回数」というフィールドをつくり、更新のつど値を+1していき、
    > 実現しようと思っていたのですがTimeStamp型というものがあるので、こちらのや
    > り方も勉強してみようと思い質問しました。

    解決したようですので、いまさら役に立たない回答かもしれませんが・・・

    型付 DataSet + TableAdapter の機能(旧データをすべて保存しておき、更新時にそれ
    と DB のデータを比較して、違っていれば更新しない)を利用してはいかがですか?

    楽観的同時実行制御でよければ、既存の DB には一切手を加えず、ウィザードを利用し
    てほとんどコードを書かずに実装できます。

    • 回答としてマーク sk7474 2009年4月2日 8:47
    2009年3月15日 0:17
  • TI-cb400さん の発言:

    ということで、フォーム1のグローバル変数に値を保持しておけばよいのか?と思い、質問をさせていただきました。

    グローバル変数というよりはパブリックな変数という意味なんですね。フォーム1にパブリックなバイト配列のプロパティを用意しておき、そこにセットするようにすれば良いでしょう。
    #グローバル変数というとアプリケーション全体にスコープがあって、常にどこからでもインスタンスに関係なくアクセスできるという印象が強くなります。

    TI-cb400さん の発言:

    素直に、DataSetやTableAdapterを利用するほうが良いのでしょうか。

    このこととフォーム1とフォーム2の間で値を渡すこととは全く関係がありません。TI-cb400さんが書かれた内容から判断するに、1件のデータを取得して更新されるようですので、データテーブルを用意するのは過剰でしょう。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク sk7474 2009年4月2日 8:49
    2009年3月15日 7:26
    モデレータ
  • TI-cb400さん の発言:

    ごDim frm As New frmPtSearch
    frm.Pt_Kihon_Info_Form = Me ' Me には今表示されている frm_ptbaseinfo のインスタンスが入っています。
    frm.ShowDialog()

    ただ、この形式ですとPrivateな変数ではエラーとなってしまいます(「Privateな変数にはアクセスができない」)

    そこで変数の宣言をPublicにすると変数へセットすることができます。

    変数はPublicでないとダメでしょうか。

    また、そもそもフォームの開き方自体から間違っているのでしょうか。

    たぶん、frmPtSearchにおいて、Pt_Kihon_Info_Formのインスタンスに対して検索結果をセットしているんですよね?
    この場合ですと、そのインスタンス上にあるフィールドはPublicでないと検索結果をセットできません。
    しかし、一般的にはこのような使い方はしません。ShowDialog()で開いたフォームは、明示的にDisposeしなければインスタンスが残ったままになります。従って通常はusing句と共に使用します。
    さて、インスタンスが残っているわけですから、frmPtSearchを閉じた後でも、フォーム1からfrmPtSearchへアクセスすることができます。従って、 フォーム1からfrmPtSearchの検索結果にアクセスして、値をセットすることができます。
    つまり、frm.Pt_Kihon_Info_Form = Meは必要ありません。以下のような感じです。End Usingを抜けると、frmへアクセスすることは保障されません。

    Using frm As New frmPtSearch  
       frm.ShowDialog()  
     
       'frmの検索結果にアクセスし、このフォーム(フォーム1)に値を取得する。  
       
    End Using 



    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク sk7474 2009年4月2日 8:48
    2009年3月17日 14:53
    モデレータ
  • 「患者」という言葉を使われていますが、これにより「医療系のシステムだ」と、想像させることができます。やろうと思えば、インターネット上のトラフィックを監視して、あなたが投稿を行っている IP アドレスを特定し、あなたが投稿している場所を絞り込むことができます。会社から投稿しているなら、あなたの会社を特定できます。その会社から発信される情報を監視すれば・・・後はご想像にお任せ。



    まず、「見せるもの」と「情報」を分離しましょう。 今、提示されている情報だと、フォーム上にデータベースの情報が全てコピーされているように思われます。TimeSpan を文字列表記するには、TimeSpan.ToString をコールすればよく、そこから元の TimeSpan に戻すには TimeSpan.TryParse すればよいのですが、TimeSpan をエンド ユーザーに見せる必要はありません。バックグラウンドに保持していれば十分です(おそらく、SurferOnWwwさんが言わんとされていること)。

    つまり、情報を2重に持ちます。データベースとやりとりするための情報と、エンド ユーザーに見せるための情報です。そして、見せるための情報と、データベースとやりとりする情報を、結束(バインド)します。すると、フォーム上での変更が、バックグラウンドの情報に自動的に反映されます。

    具体的には、「Visual Studio 2005による Windowsデータベース・プログラミング」などを見ればよいかと。

    そんな根本的に作り直すようなことなどできない、ということであれば、なんにしても“ユーザーに見せる必要はない”のですから、フォームに TimeSpan 型の Public な変数をひとつ用意すればよいでしょう。“ユーザーが見たり変更したりする必要はない”のですから。


    Jitta@わんくま同盟
    • 回答としてマーク sk7474 2009年4月2日 8:48
    2009年3月16日 3:14

すべての返信

  •  

    > レコードを更新する際に、今まではAccessを使用していたので、更新チェック用の列を用意しておき、その値を
    > 更新実行前に読み込んだときの内容と比較して、読み込んだときと同じ状態であるかを確認して更新しておりました。

    楽観的 or 悲観的同時実行制御の話とは違うのですか?

    2009年3月14日 1:25
  • ご回答ありがとうございます。

    楽観的同時実行制御をしたいと思っています。

    初めは、「更新回数」というフィールドをつくり、更新のつど値を+1していき、実現しようと思っていたのですが
    TimeStamp型というものがあるので、こちらのやり方も勉強してみようと思い質問しました。
    2009年3月14日 1:57
  • TI-cb400さん の発言:

    問題は、
    1.TimeStamp型のデータをテキストボックスに格納できない
    バイナリデータなので、String型に変換しようと思い、以下のように記述をしたのですが、

    Dim TimeStampValue(7) As Byte

    TimeStampValue = CByte(DT.Rows(0)("pt_ts"))

    「型Byteの値をByteの一次元配列に変換できません」とエラーになります。

    いろいろと調べてはいるのですが、どうしたらよいかがわかりません。

    2.TimeStamp型を比較に用いるとき、テキストボックスに値を保持しておき、それを更新の際に比較をすると
    いう使い方が一般的なのか、それとも別の方法を用いて比較を行うのか。

    1.まず、TimeStampは8バイトですので、8バイトのバイト配列として定義して下さい。そのうえで、
    TimeStampValue = CType(DT.Rows(0)("pt_ts"), Byte())
    で良いと思います。

    2.テキストボックスに保存する必要はありません。8バイトのバイト配列に保存しておき、レコード更新時にその値を使って更新を行います。更新に失敗した場合は、誰か他の人が更新を行ったということですから、それをユーザーに知らせます。この辺りは楽観的同時実行制御の考え方と全く同じです。


     
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年3月15日 5:46
    • 回答としてマークされていない TI-cb400 2009年3月15日 6:15
    • 回答としてマーク sk7474 2009年4月2日 8:46
    2009年3月14日 8:22
    モデレータ
  • ご回答ありがとうございます。

    ご提示に方法でできました。

    まだまだ、わからないことだらけなので、また困ったときはどうかよろしくお願いします。

    ありがとうございました。
    2009年3月14日 18:45
  • > 楽観的同時実行制御をしたいと思っています。
    >
    > 初めは、「更新回数」というフィールドをつくり、更新のつど値を+1していき、
    > 実現しようと思っていたのですがTimeStamp型というものがあるので、こちらのや
    > り方も勉強してみようと思い質問しました。

    解決したようですので、いまさら役に立たない回答かもしれませんが・・・

    型付 DataSet + TableAdapter の機能(旧データをすべて保存しておき、更新時にそれ
    と DB のデータを比較して、違っていれば更新しない)を利用してはいかがですか?

    楽観的同時実行制御でよければ、既存の DB には一切手を加えず、ウィザードを利用し
    てほとんどコードを書かずに実装できます。

    • 回答としてマーク sk7474 2009年4月2日 8:47
    2009年3月15日 0:17
  • ご回答ありがとうございます。

    ご提示の件ですが、今回の質問に関係があるので一緒にご質問をさせていただこうかと
    思ったのですが、やはり内容が別物であるので、控えさせていただいておりました。

    今後、試してみたいと思います。
    2009年3月15日 5:57
  • いったんは、解決したといっておきながら、もう1点不明な点がありますので、お願いします。

    最初の質問の内容を実行している場所なのですが、個人情報を表示するフォーム(フォーム1)から
    検索用のフォーム(フォーム2)を呼び出します。

    フォーム2で対象となる患者を選択して、検索ボタンを押し、フォーム1に対象となる患者の個人情報を
    表示します。

    フォーム2において、データを取得するクラスを呼び出し、そのときに最初の質問でしたTimeStamp型の
    データも取得します。

    このTimeStamp型のデータを格納する変数ですが、グローバル変数で宣言するのでしょうか。

    それとも、クラスのプロパティでセットしておくものでしょうか。

    どうか、よろしくお願いします。
    2009年3月15日 6:28
  •  
    TI-cb400さん の発言:

    このTimeStamp型のデータを格納する変数ですが、グローバル変数で宣言するのでしょうか。

    それとも、クラスのプロパティでセットしておくものでしょうか。


    う~ん、これだけでは何とも答えようがないのですが、もしフォーム1からのみ表示されたデータを更新するのであれば、一般的にはフォーム1のプライベートなフィールドで十分でしょう。フォーム1から更新する際に、そのフォーム1クラスでさえ見えればよいのですから。

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年3月15日 6:37
    モデレータ
  • ご回答ありがとうございます。

    また、わかりにくい質問で大変申し訳ありません。

    ただ、一番最初のところに戻るのですが、フォーム1にデータを表示させた後は、データを取得したクラスをを
    呼び出したフォーム2(検索フォーム)は閉じてしまいます。

    そこで、フォーム2のローカル変数に更新管理用のフィールドのデータを保持していても何の役にも立ちません。

    そこで考えたのが、
    1.
    フォーム1に更新管理用のTimeStamp型のデータを入れておくテキストボックスを用意して
    そこにデータを保持しておく。

    2.
    フォーム1にグローバル変数を用意しておき、そこにTimeStamp型のデータを保持しておく。

    という2種類でした。

    しかし、TimeStamp型のデータはByte型の一次元配列であり、そのままではテキストボックスに格納する
    ことができませんでした。(Cstr関数を利用してもダメでした)

    ということで、フォーム1のグローバル変数に値を保持しておけばよいのか?と思い、質問をさせていただきました。

    今回のケースのような場合、どのように行ったほうが良いのでしょうか。
    素直に、DataSetやTableAdapterを利用するほうが良いのでしょうか。

    どうか、よろしくお願いします。
    2009年3月15日 7:10
  • TI-cb400さん の発言:

    ということで、フォーム1のグローバル変数に値を保持しておけばよいのか?と思い、質問をさせていただきました。

    グローバル変数というよりはパブリックな変数という意味なんですね。フォーム1にパブリックなバイト配列のプロパティを用意しておき、そこにセットするようにすれば良いでしょう。
    #グローバル変数というとアプリケーション全体にスコープがあって、常にどこからでもインスタンスに関係なくアクセスできるという印象が強くなります。

    TI-cb400さん の発言:

    素直に、DataSetやTableAdapterを利用するほうが良いのでしょうか。

    このこととフォーム1とフォーム2の間で値を渡すこととは全く関係がありません。TI-cb400さんが書かれた内容から判断するに、1件のデータを取得して更新されるようですので、データテーブルを用意するのは過剰でしょう。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク sk7474 2009年4月2日 8:49
    2009年3月15日 7:26
    モデレータ
  • trapemiya の発言:

    グローバル変数というよりはパブリックな変数という意味なんですね。フォーム1にパブリックなバイト配列のプロパティを用意しておき、そこにセットするようにすれば良いでしょう。

    ちょっと訂正します。フォーム2はフォーム1からShowDialog()で開かれていると思いますので、フォーム1にパブリックなプロパティを用意する必要はなく、単にフォーム1にプライベートな変数を用意し、そこにTimeStamp値を入れれば良いと思います。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    2009年3月15日 7:39
    モデレータ
  • 「患者」という言葉を使われていますが、これにより「医療系のシステムだ」と、想像させることができます。やろうと思えば、インターネット上のトラフィックを監視して、あなたが投稿を行っている IP アドレスを特定し、あなたが投稿している場所を絞り込むことができます。会社から投稿しているなら、あなたの会社を特定できます。その会社から発信される情報を監視すれば・・・後はご想像にお任せ。



    まず、「見せるもの」と「情報」を分離しましょう。 今、提示されている情報だと、フォーム上にデータベースの情報が全てコピーされているように思われます。TimeSpan を文字列表記するには、TimeSpan.ToString をコールすればよく、そこから元の TimeSpan に戻すには TimeSpan.TryParse すればよいのですが、TimeSpan をエンド ユーザーに見せる必要はありません。バックグラウンドに保持していれば十分です(おそらく、SurferOnWwwさんが言わんとされていること)。

    つまり、情報を2重に持ちます。データベースとやりとりするための情報と、エンド ユーザーに見せるための情報です。そして、見せるための情報と、データベースとやりとりする情報を、結束(バインド)します。すると、フォーム上での変更が、バックグラウンドの情報に自動的に反映されます。

    具体的には、「Visual Studio 2005による Windowsデータベース・プログラミング」などを見ればよいかと。

    そんな根本的に作り直すようなことなどできない、ということであれば、なんにしても“ユーザーに見せる必要はない”のですから、フォームに TimeSpan 型の Public な変数をひとつ用意すればよいでしょう。“ユーザーが見たり変更したりする必要はない”のですから。


    Jitta@わんくま同盟
    • 回答としてマーク sk7474 2009年4月2日 8:48
    2009年3月16日 3:14
  • ご回答ありがとうございます。

    現在、フォーム2はフォーム1から以下の形で開いております。

    Dim frm As New frmPtSearch
    frm.Pt_Kihon_Info_Form = Me ' Me には今表示されている frm_ptbaseinfo のインスタンスが入っています。
    frm.ShowDialog()

    ただ、この形式ですとPrivateな変数ではエラーとなってしまいます(「Privateな変数にはアクセスができない」)

    そこで変数の宣言をPublicにすると変数へセットすることができます。

    変数はPublicでないとダメでしょうか。

    また、そもそもフォームの開き方自体から間違っているのでしょうか。
    2009年3月17日 12:32
  •  

    > 変数はPublicでないとダメでしょうか。

    ダメです。private にするなら public なプロパティを作って、それを通じて
    アクセスするのが一般的です。

    基本的なことが理解できてないようで、もう少し勉強が必要なように思えます
    が・・・

    2009年3月17日 14:23
  • TI-cb400さん の発言:

    ごDim frm As New frmPtSearch
    frm.Pt_Kihon_Info_Form = Me ' Me には今表示されている frm_ptbaseinfo のインスタンスが入っています。
    frm.ShowDialog()

    ただ、この形式ですとPrivateな変数ではエラーとなってしまいます(「Privateな変数にはアクセスができない」)

    そこで変数の宣言をPublicにすると変数へセットすることができます。

    変数はPublicでないとダメでしょうか。

    また、そもそもフォームの開き方自体から間違っているのでしょうか。

    たぶん、frmPtSearchにおいて、Pt_Kihon_Info_Formのインスタンスに対して検索結果をセットしているんですよね?
    この場合ですと、そのインスタンス上にあるフィールドはPublicでないと検索結果をセットできません。
    しかし、一般的にはこのような使い方はしません。ShowDialog()で開いたフォームは、明示的にDisposeしなければインスタンスが残ったままになります。従って通常はusing句と共に使用します。
    さて、インスタンスが残っているわけですから、frmPtSearchを閉じた後でも、フォーム1からfrmPtSearchへアクセスすることができます。従って、 フォーム1からfrmPtSearchの検索結果にアクセスして、値をセットすることができます。
    つまり、frm.Pt_Kihon_Info_Form = Meは必要ありません。以下のような感じです。End Usingを抜けると、frmへアクセスすることは保障されません。

    Using frm As New frmPtSearch  
       frm.ShowDialog()  
     
       'frmの検索結果にアクセスし、このフォーム(フォーム1)に値を取得する。  
       
    End Using 



    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク sk7474 2009年4月2日 8:48
    2009年3月17日 14:53
    モデレータ
  • ご回答ありがとうございます。

    SurferOnWwwさんへ
    確かに基本的なことが理解できていないことは認めます。
    ただ、参考書を読むだけではなかなかこれらのことは理解できず、かといってサンプルプログラムだけでは
    なかなか、現実に即したものでないことが多く、なぜそのようなことを行うのか、という点がわからず
    プログラムの意味がつかみにくいということがあり、実際に利用するアプリケーションを作成しながら
    勉強するという方法をとっています。

    いいわけですが、そのため、ちぐはぐなご質問となってしまうことを、大変申し訳なく思っています。

    trapemiyaさんへ
    まさにおっしゃるとおりのことをやっています。
    今は試せる環境にないので、明日試してみます。

    今回提示したコードは、以前こちらの掲示板で、2つのフォーム間での値のやり取りをするにはどうしたら
    良いかということでご質問をさせていただいたときのコードなのですが、今回のように検索値のみを
    取得する場合は、ShowDialogを利用すればよいのですね。

    少しずつですが、成長できればと思っています。

    また、テストした結果のご報告をしたいと思います。
    2009年3月18日 13:09
  • 複数のフォームを表示したい、データを受け渡ししたい、という質問は、あちらこちらで頻繁に目にします。そんなに難しいですかねぇ?

    とにかく、参考になればと、解説も書いたりしています→.NET 2.0 / Windows Form / マルチ ウィンドウズ フォーム [wankuma.com]


    ここで書くのをお許しください。
    マイクロソフトを始め、各種開発ツールの宣伝には、「簡単にできる」という言葉が使われます。確かに、簡単にできます。しかしそれは、“知っている人が”、“以前に比べて”、簡単にできる、なのです。アプリケーションの作り方をまったく知らない人が、ゼロから簡単に作ることができるわけではありません。ここの所を、間違えないでいただきたいと思います。

    まず、MSDN ライブラリを参照する癖を付けてください。読んでわからなければ、2度3度と、繰り返しよんでください。その上で、本屋さんに売られている本を読んでください。まず立ち読みして、「これなら最後まで読み通せそうだ」と思える本を選んでください。それを繰り返すうちに、最初に立ち読みしたときには「これは理解できない」と思っていた本が理解できるようになります。

    MSDN ライブラリは、基本です。これを読まないことには始まりません。書店で売られている本は、何かのテーマがあって、書かれています。そのテーマが、自分の目的と一致すれば、とてもわかりやすい本になります。参考書を読んでも理解できないのは、自分が求めているものと、参考書が書かれた目的が一致していないからです。ですから、一致するものを見つけてください。


    Jitta@わんくま同盟
    2009年3月19日 7:37
  • こんにちは。中川俊輔です。

    皆様、回答ありがとうございます。

    TI-cb400さん、フォーラムのご利用ありがとうございます。
    勝手ながら、有用な情報と思われる回答へ回答マークをつけさせていただきました。

    よろしければ、その後の結果もぜひ投稿してください!

    今後ともフォーラムをよろしくお願いします。
    それでは!
    マイクロソフト株式会社 フォーラム オペレータ 中川 俊輔
    2009年4月2日 8:52