none
VB2008でTableAdapteを使ったチェックボックスの更新 RRS feed

  • 質問

  • 現在SQLServerExpress2008に対しVB2008でTableAdapter、DataBindingsを使ってデータ更新を実施しています。

    フォームにテキストボックスのみを配置した場合は、テキストボックスが多数あっても更新処理は変わりませんが、チェックボックスを多数配置すればするほど更新処理が遅くなります。使い方等に問題があれば教えてください。

    配置方法はフォームにテキストボックス2個、チェックボックス22個を配置しDataBindingsのテキスト、Checkedにフィールドを指定し

    保存ボタンに 以下のコードを設定

    BindingSource.EndEdit()

    TableAdapter.Update(Dataset.テーブル)

    ※EndEdit()に処理がかかっているように思えます。5秒ぐらい。テキストだけだと1秒以内で処理される

    2014年7月9日 23:10

回答

  • minoru_shiraishi さま 拝見しました。

    書き忘れましたが、先程の例は、Boolxx は Null 許容のままです。
    これで、今回は、特に問題を生じませんが(原因ではないと思います。)、
    DB 側が3値(0,1,Null) ソフト側が2値(True,False) となる構成は注意が必要ですので、
    特に要求されない場合には、DB 側を Null 許容しない・初期値設定にされる事をお勧めします。(脱線)

    画面でチェックボックスは データソースの列を デザイナ画面に ドラッグドロップしただけです。

    自動生成される xxxDataSet.xsd は、元になる DB から各種の機能を作っていますので、
    もし、DB の構成を弄るような場合には、TableAdapter をウィザードで再構成する必要があります。
    実は今回の例でも、最初 Id 列を入れずに画面を作った為 レコードを一意認識出来ず、 UpdateCommand が生成されなかったので、再度 DB 調整の上、データソース指定および画面再作成しました。(初心者レベルです、私)
    xxxDataSet.xsd 画面で xxxTableAdapter の プロパティ タブで UpdateCommand を展開し、CommandText にMouseHover すると、自動作成されたSQL コードが見れます。
    恐らくですが、この様に、作業をし直す事で、正常動作に戻る場合も多いです。

    先の例は簡単ですから、雛形・テスト用と割り切って、お作りになって、動作確認されては如何ですか。
    • 編集済み ShiroYuki_Mot 2014年7月11日 2:04 trapemiya さまのご指摘を受け、文章一部削除
    • 回答としてマーク minoru_shiraishi 2014年7月11日 12:02
    2014年7月10日 13:03

すべての返信

  • >※EndEdit()に処理がかかっているように思えます。5秒ぐらい。テキストだけだと1秒以内で処理される

    EndEdit()は自動的に実行されますから、明に実行する必要はありませんので、コメントアウトしてみて下さい。
    もし、これで変わらなければ、同時実行制御を行うためにSQLが複雑になっている可能性があります。
    TableAdapter構成ウィザードの詳細オプションで、オプティミスティック同時実行制御のチェックボックスを外すと変化ありますでしょうか?


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

    2014年7月10日 0:18
    モデレータ
  • > EndEdit()は自動的に実行されますから、明に実行する必要はありません

    どのタイミングで「自動的に実行」されるのでしょうか?

    BindingSource.EndEdit() メソッドは、データの保存の直前に実行されるように、ウィザードが自動生成するコードには含まれるようになっています。そのタイミングでは明示的に実行する必要があると思いますが。

    ちなみに、以下のチュートリアルの「8. データ保存時の処理」のセクションには "customersBindingSource の EndEdit メソッドを呼び出していますが、これは顧客データの編集フォームでの編集を確定させるためのものです。これによりフォームで編集された内容がデータセットにすべて反映されます。" という説明があります。

    10 行でズバリ !! 非接続型のデータ アクセス (ADO.NET) (C#)
    http://code.msdn.microsoft.com/windowsdesktop/10-ADONET-C-cbfe7688


    質問者さんのケースでは、自分が想像できる範囲を超えた何か特別なことをしていて、上記のような一般的な話は当てはまらないのかもしれませんが・・・

    2014年7月10日 1:53
  • >そのタイミングでは明示的に実行する必要があると思いますが。

    申し訳ない、その通りです。
    BindingSourceでしたね。BeginEdit()を自働的に実行するコントロールと勘違いしてしまいました。
    ご指摘、ありがとうございました。


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

    2014年7月10日 3:00
    モデレータ
  • >EndEdit()は自動的に実行されますから、明に実行する必要はありませんので、コメントアウトしてみて下さい。

    EndEdit()をコメントアウトするとデータが保存できません。

    >TableAdapter構成ウィザードの詳細オプションで、オプティミスティック同時実行制御のチェックボックスを外すと変化ありますでしょうか

    変化ありません。

    2014年7月10日 4:00
  • >EndEdit()をコメントアウトするとデータが保存できません。

    フォームにBindingNavigatorが表示されており、前後にレコードが移動できる形式のフォームですしょうか? であれば、レコードを移動すれば編集が確定されますので、移動する前のレコードはEndEdit()が無くても保存されます。レコードが移動しなければ編集は確定されませんので、EndEdit()が必要です。
    つまり、10件入力して保存ボタンを押した場合、最後のレコードは保存されません。最後のレコードを保存するには、EndEdit()が必要です。
    もし、EndEdit()で時間がかかっているのであれば、このようにしてEndEdit()を削除してみれば保存が速くなるはずですし、速くならなければEndEdit()の実行が原因ではないことになります。
    また、StopWatchクラスを使って、それぞれの処理時間を計測されてみてはいかがでしょうか?

    処理時間を正確に計測するには?[2.0のみ、C#、VB]
    http://www.atmarkit.co.jp/fdotnet/dotnettips/412stopwatch/stopwatch.html


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

    • 編集済み trapemiyaModerator 2014年7月10日 4:25 誤字修正(何度もすみません。いかんなぁ・・・)
    2014年7月10日 4:15
    モデレータ
  • >レコードを移動すれば編集が確定されますので、移動する前のレコードはEndEdit()が無くても保存されます。レコードが移動しなければ編集は確定されませんので、EndEdit()が必要です。

    私の早合点もあって先に誤ったことを述べてしまいましたので、この辺りの動作を調べてみました。
    まず、BindingSourceのEndEdit()メソッドですが、これは内部的にCurrencyManagerのEndCurrentEdit()メソッドを呼び出します。一方、BindingNavigatorでレコードを移動した場合も、同じEndCurrentEdit()メソッドを呼び出していました。結果、レコードを移動すれば、BindingSourceのEndEdit()を呼び出したことになりますので、引用のような動作をすることになります。ちなみに、BindingSourceはCurrencyManagerをラップするようなクラスであり、BindingSourceが登場してからはCurrencyManagerを直接いじることは少なくなっています。

    とりあえず今回はBindingNavigatorは関係ないかもしれませんが・・・

    (追記)
    DataGridViewなどは1件だけ編集しても、保存ボタンを押すためにDataGridViewからフォーカスが外れますから、その際に上記のようなことがおこります。よって、この場合はBindingSourceのEndEdit()メソッドは必要ありません。


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

    2014年7月10日 5:11
    モデレータ
  • minoru_shiraishi さま よろしく。

    Id,Text1,Text2,Bool01,~,Bool20 からなるテーブルを用意し、
    (データ型は Boolxx : bit / 他は nvarchar / Id のみ一意・主キー / SQLServer Compact 3.5 )
    型付データセットを自動作成し、Form 上に 各々配置しました。  (VB2008sp1EE x86)
    更に更新用のボタンを配置し、以下のコードで動かした所、問題は生じません。
    処理待ちの遅延はありませんが。

    Public Class Form1

    Private Sub TestBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TestBindingNavigatorSaveItem.Click Me.Validate() Me.TestBindingSource.EndEdit() Me.TableAdapterManager.UpdateAll(Me.TestDataBaseBool20DataSet) End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'TODO: このコード行はデータを 'TestDataBaseBool20DataSet.Test' テーブルに読み込みます。必要に応じて移動、または削除をしてください。 Me.TestTableAdapter.Fill(Me.TestDataBaseBool20DataSet.Test) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.TestBindingSource.EndEdit() Me.TestTableAdapter.Update(TestDataBaseBool20DataSet.Test) End Sub End Class


    EndEdit() 以外の所に、何か、問題がありそうな気がします。
    自動作成のテーブルアダプタがちゃんと機能していないとか。

    • 編集済み ShiroYuki_Mot 2014年7月10日 6:55 タイプミス訂正
    2014年7月10日 6:43
  • SuroYuki_Motさん回答ありがとうございます。

    会社からの投稿ができなくなりました(セキュリティー上かな・・・・)


    BindingNavigatorを利用して確認したところおかしな動きがわかりました。

    チェックボックスをチェックしてデータを保存した場合はSQLServerのTrueで保存されるが、チェックしない場合はNULL値のままでした。(SQLServerのフィールドタイプはbitです)

    明日会社で一度規定値をFalseにしてから再度確認してみます。

    そもそもチェックボックスのDataBindingsはCheckedにフィールドを設定していますが間違っていますか?

    TableAdapterを使った開発は初心者で申し訳ありませんが、ご教授お願いいたします。

    2014年7月10日 11:45
  • minoru_shiraishi さま 拝見しました。

    書き忘れましたが、先程の例は、Boolxx は Null 許容のままです。
    これで、今回は、特に問題を生じませんが(原因ではないと思います。)、
    DB 側が3値(0,1,Null) ソフト側が2値(True,False) となる構成は注意が必要ですので、
    特に要求されない場合には、DB 側を Null 許容しない・初期値設定にされる事をお勧めします。(脱線)

    画面でチェックボックスは データソースの列を デザイナ画面に ドラッグドロップしただけです。

    自動生成される xxxDataSet.xsd は、元になる DB から各種の機能を作っていますので、
    もし、DB の構成を弄るような場合には、TableAdapter をウィザードで再構成する必要があります。
    実は今回の例でも、最初 Id 列を入れずに画面を作った為 レコードを一意認識出来ず、 UpdateCommand が生成されなかったので、再度 DB 調整の上、データソース指定および画面再作成しました。(初心者レベルです、私)
    xxxDataSet.xsd 画面で xxxTableAdapter の プロパティ タブで UpdateCommand を展開し、CommandText にMouseHover すると、自動作成されたSQL コードが見れます。
    恐らくですが、この様に、作業をし直す事で、正常動作に戻る場合も多いです。

    先の例は簡単ですから、雛形・テスト用と割り切って、お作りになって、動作確認されては如何ですか。
    • 編集済み ShiroYuki_Mot 2014年7月11日 2:04 trapemiya さまのご指摘を受け、文章一部削除
    • 回答としてマーク minoru_shiraishi 2014年7月11日 12:02
    2014年7月10日 13:03
  • SuroYuki_Motさんこんばんは

    明日もう一度テスト画面で作り直して確認してみます。

    ありがとうございました。またご報告いたします。

    2014年7月10日 13:36
  • チェックボックスをチェックしてデータを保存した場合はSQLServerのTrueで保存されるが、チェックしない場合はNULL値のままでした。(SQLServerのフィールドタイプはbitです)

    Checkedプロパティにバインドしているということですが、NULLはバインドできませんので、CheckBoxはその時点で何の動作もしません。よって、初期状態はデフォルトのチェックされていない状態で表示されることになります。もし、最初のレコードがtrueで、次のレコードがNULLであれば、最初はバインドが成功してチェックされた状態で表示されますが、次のレコードに移った際にはバインドが失敗しますからCheckBoxでは何の変化も起こらず、よって、最初のチェックされた状態のままになります。つまり、実際のレコードとは異なるチェック状態になっています。
    この状態でユーザーがチェック状態を操作すればバインドが成功しますから、その値でレコードに書き込まれます。よって、レコードはNULLではなくなります。

    >そもそもチェックボックスのDataBindingsはCheckedにフィールドを設定していますが間違っていますか?

    データベース上でNULLを許容していなければ間違っていませんが、許容している場合はCheckStateにバインドすべきです。CheckStateはNULLの状態を表すことができます


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

    2014年7月11日 1:36
    モデレータ
  • trapemiya さま ご指摘ありがとうございます。

    今、Null 許容の列からドラッグドロップして自動作成した Checkbox のプロパティを見て見ました。
    DataBindings の項目は3つあり( CheckAlign / Checked / CheckState )、
    このうち前2つは (なし) 、CheckState に xxxBindingSource の列が設定されています。

    ここが、今回のご質問の原因のひとつですね。

    PS: CheckBox のバインド対象が何種類かあるとは知りませんでした。いい勉強になりました。
    • 編集済み ShiroYuki_Mot 2014年7月11日 1:57 列 を Null 許容の列 に変更
    2014年7月11日 1:54
  • みなさんのご指摘どおり、CheckBoxのCheckStateに値を設定したことで、保存処理も高速になりました。

    NULLはDataSetデザイナ編集画面で規定値をFalseに設定することでNULL入力を回避できました。

    コントロールを手動で設定したことが原因でした。

    私自身勉強になりました。みなさんありがとうございました。

    2014年7月11日 12:01
  • > NULLはDataSetデザイナ編集画面で規定値をFalseに設定することでNULL入力を回避できました。

    DB の方で NULL 不許可にしたほうが良いと思います。(それができない理由があれば話は別ですが)


    > コントロールを手動で設定したことが原因でした。

    以下のページの「図 14」のようにドラッグ&ドロップすれば、適切に DataBindings が設定されたコードが自動生成されます。CheckBox コントロールなら、自動的に CheckState に設定されます。

    10 行でズバリ !! 非接続型のデータ アクセス (ADO.NET) (C#)
    http://code.msdn.microsoft.com/windowsdesktop/10-ADONET-C-cbfe7688

    上記の例は 2 つのテーブルを扱ってますが、テーブルが一つならもっと簡単で、自力では一行もコードを書かずに型付 DataSet + TableAdpater を利用した Windows Forms アプリを作成できます。

    一度試してみることをお勧めします。開発工数が大幅に削減できるはずです。

    2014年7月12日 5:26