データセットデザイナは DB 構造の変更にちょー弱い
データベースの設計を完了させてからプログラムの設計へ進みなさい、とはよく言われることではあるんですが。
実際には、ユーザー要望の変更や追加・削除、連携している外部システムからのインターフェイス変更、旧システムからのしがらみやデータ移行時等に判明する驚愕の新事実、関連法規の改正等々ありまして、とてもじゃありませんがそんな理想論につきあっちゃいられません。
データベースの構造は常に変わり得るんです。
それを前提に設計・製造、運用開始後のメンテナンスまで含めて考えていかにゃならんのです。
完全内製で周囲のしがらみに一切影響されない、ってんなら理想論を通せる可能性もあるかもしれませんが。
ではそんなこんなで DB 構造の一部が変わっちゃった時に、データセットデザイナで作ったテーブルアダプタ等はどうなってしまうのか。
気になりませんか私は気になります。
ということで、そのへんを調べてみました。
検証環境 自作マシン(Core2QuadQ9400 2.66GHz/4GB)
Windows7 Ultimate(6.1.7600) – x86
VisualStudio2008Pro(VB) 9.0.30729.1SP/.NET Framework 3.5SP1
Oracle Database 11g 11.1.0.6.0
Oracle Developer Tools for Visual Studio 11.1.0.7.20Windows XP Professional SP3
VisualStudio2008Pro(VB) 9.0.21022.8/.NET Framework 3.5SP1
Oracle Developer Tools for Visual Studio.NET 11.1.0.6.20
まあこんな感じでごく小さなテーブルをひとつこしらえて。
新規で Windows フォームアプリケーションを作成、Form に Button と DataGridView を 1 つずつ追加して。
データセット項目も追加して、サーバーエクスプローラから上述のテーブルをドラッグ & ドロップでテーブルアダプタを追加して。
先ほどフォームに追加した Button の Click イベントに、テーブルアダプタで取得した結果を DataGridView の DataSource にひも付けるコードを記述して。
Private Sub Button1_Click( _
ByVal sender As System.Object, ByVal e As System.EventArgs _
) Handles Button1.Click
Using ta = New DataSet1TableAdapters.TBL_CHILD40TableAdapter
DataGridView1.DataSource = ta.GetData()
End Using
End Sub
実行して Button をクリックすれば、先ほどのテーブルの中身が見えるわけです。
ここまではまあふつーです。
さて、ここでユーザーからクレームが!
STR_HAN には 40 文字まで入るようにしてもらえないと困る!
ええーこないだの打ち合わせでは 20 文字で充分ってたじゃないすかー(;-;)。
しかたがないので先ほどのテーブルの STR_HAN フィールドを、CHAR(20) → CHAR(40)に修正して。
先ほどのプログラムをもう一度実行すると、
ええーなんだかすっごくわけのわからない状態に。
エラー出るならせめてちゃんと例外出して止まってくれればまだ手掛かりもあるってもんなのにー。
以上の振る舞いが 11.1.0.7.20 。同じことを 11.1.0.6.20 でやってみると、
おお、こちらはちゃんと例外発生で止まります。けど、
ConstraintException はハンドルされませんでした。
制約を有効にできませんでした。Null 以外の値、一意な値、あるいは外部キーですが、この制約の違反が 1 つ以上の行で発生しています。
ってやっぱりよくわからない説明になっています。
とまあ、いきなり vshost.exe が停止したりよくわからない例外が発生するとどう調べて/直していいのか途方に暮れるんですけれども、今回はフィールドが保持するバイト数を大きくしちゃったのが原因だということはわかっています。
TableAdapter を生成した時に、けっこうな量のソースコードがデータセットの Designer.vb に出力されるんですが、その中の「DataSetクラス」の中の「DataTableクラス」の中の InitClass メソッドの中で、文字フィールドのデータを受ける変数に最大バイト数を設定しているんですね。
ここが 20 バイトなのに 40 バイト分のデータがやってきてしまうと、上述の不具合が発生してしまうわけです。
実際、この行の右辺を手で 20 → 40 に書き換えてやると、正常に動作します。
しかし、現実の作業の中では、DB 構造のどこをどう直したのかがよくわからない場合もあります。
というか、数百項目もあるテーブルをいくつも結合した SQL 文から生成した TableAdapter だったりすると、細心のテーブル設計書とソースを照らし合わせるだけでたいそう時間がかかります。
なんとかここはデータセットデザイナから最新の状況に更新できないものか。
と思っていろいろ調べてみたんですが、変更されたフィールドを TableAdapter の枠の中から右クリックし、プロパティウィンドウに表示された MaxLength プロパティを手で修正するしか方法がないみたいなんです。
テーブルのどこをどう修正しなければならないかあらかじめわかっているんであれば、そもそもエラーが出てびっくり、なんて状況にはならないわけですし。
テーブルアダプタ作成時のコードジェネレータ(と言うんでしょうか)を再実行させたいだけなんですけどねー…どう探してもそんな機能は見つかりませんでした。
猿頁 » Blog Archive » データセットデザイナの反応が遅い でお話ししましたが、直埋めした接続文字列を ConnectionString に外出しする作業も、実はなかなか思い通りに進みません。
後から切り替えようとしても、他の .xsd ファイルで先に作っていた ConnectionString を共有可能と認識してくれず、ConnectionString1、ConnectionString2、…と同じ接続情報がどんどん増えていったりします。
複雑な SQL 文をがんがん埋め込んだテーブルアダプタを 1 つのデザインウィンドウあたりに 10 も 20 も詰め込むと、ウィザード完了時・デザイナファイル保存時に実行されるコードの自動生成が動作途中でギブアップしてしまい、まともに動作しない中途半端なコードになってしまうこともあるような気がします。
ので、動作がおかしくなった場合はヘタにていねいに原因を探ってみたり、デザイナ画面をいじり回してなんとかしたりするよりは、設定パラメータと SQL 文を拾い上げて、同じテーブルアダプタ(もしくは .xsd ファイル自体)を新規で作り直してしまった方が安全確実高効率だ、というのが今のところの私の実感です。









