BindingSource

NETFrameworkは汎用的なフレームワークなので、データバインディングについてもデータベース連結だけをターゲットに組まれているわけではありません。そのため、データベース応用システム開発に使用した場合、Accessなどのテータベース開発ツールと比べると少しずつ回りくどいというか使いにくい面があります。そのためデータバインディングやTableAdapterなどの枠組みを使わずもっと単純なクラスのみを使って開発するPONO(Plain Old Net Object)という考え方があるようです。もともとはPOJOから派生した言葉らしいです。Visual Basic 6においてもDataEnvironmentを使って開発する方は意外に少なかったと記憶しています。

私はNETFrameworkに用意されている枠組みを活かしながら、使いにくいところは別のクラスで置き換えたり、拡張したりしながら使っています。TableAdapterは基底型がObjectでありライブラリ化が難しいのでほとんど使わず、同等機能のクラスを新たに作成しました。BindingSourceはこれを継承してデータベース連結に特化したTableBindingSourceを作成して使用しています。またTextBoxなどUI部品はNullの扱いが苦手なので、Nullも自然に扱えるように拡張しています。このような拡張ができてしまうのもNETFrameworkの汎用性のおかげなのですが。

このような拡張の中で少し引っかかった点がありますのでご紹介します。BindingSourceにはバインドがサスペンドしている状態があります。DataTableに全くデータがない場合に暗黙的にサスペンド状態になります。明示的に状態を切り替えるにはSupendBindingとResumeBindingを使います。IsBindingSuspendedがその状態を取得するのに使われます。ところがIsBindingSuspendedが内部で保持しているサスペンドの状態を必ずしも表していないことがあるようです。データが全くなくなって暗黙的なサスペンド状態でAddNewを呼び出しても再開してくれない場合があったので、ResumeBindingを呼び出しました。しかしそれでも再開してくれないのです。

1
2
3
If IsBindingSuspended Then SuspendBinding() 'バグ対策、内部状態が一致しない場合がある
Dim newRow As Object = AddNew()
ResumeBinding() 'バグ対策、SuspendBindingに関連して必要

そこで対策としてIsBindingSuspendedの場合にSuspendBinding()を呼ぶことで本当のサスペンド状態?になってAddNew後のResumeBindingが働くようになりました。