2015年3月23日月曜日

VB 型付データセット と DataGridView の落とし穴 (VB2008SP1)

最新版の Visual Basic でも、そうなのか、試していないので、 参考迄に ご覧下さい。
大変、重宝する DataGridView ですし、Visual Studio が自動生成する型付データセットの存在も拍手ものです。
大抵の場合、このふたつの組み合わせは、簡単に、一覧表の機能を実現します。
凄く良く考えられていて、万全。  の筈、なのですが ... 。  う~ん、Column Input Length !。


ひとつ、落とし穴がありました。
様々な場所で説明される、一番簡単な、 DataGridViewを使ったデータベースの利用方法なのですが ... 。
今迄、幾つか書いて来ましたが、初めて、ぶつかった 壁 です。  壁 と言う程ではないですが ... 。.


DataBase DataSet DataGridView と、お互いに結び付けられた関係ですが、
自動生成された 型付データセット(データソース) から、 DataGridView を配置すると、
元の DataBase DataSet で規定された データ型 や サイズ(大きさ・長さ) は、
DataGridView には反映されません。  表面的には。

例えば、DataBase で、INT32 (Size=4) と指定すると、
DataSet では、System.Int32 MaxLength=-1 、
DatagridView では、Type=String Name=DataGridViewTextBoxColumn1 MaxInputLength=32767 、
と設定されます。
更に、
元の DataBase が Nvarchar (文字) で、 Size=100 でも、 Size=8 でも、 Size=1000 でも、
DataSet では、これを反映するのに対して、
DataGridView では、Type=String Name=DataGridViewTextBoxColumn1 MaxInputLength=32767 です。

DataGridView が表示や入力を前提に設計されている為、文字型中心の既定値が入っています。
そして、MaxInputLength は変わらないのです。

仮に、データベース上は INT32 等の数値型でも、アルファベットや数値型の範囲を超える値が入力出来てしまいます。
数値型で数字に限る方法は、良く見掛けますし、良く質問や問題として挙がるのですが ... 。
   素人考えですが、DataGridView 自身の制限と、結び付けられた DataSet 上の制限とは、別にあって、
   Cell を Validate 出来ても、DataSet の制約を確認した段階で、値が不正になるのでは ... 。  う~、難しい ... 。


ちょっと、脱線。
データベースアプリは Visual Studio では、初めにデータベースありき の世界です。
従って、データベースの設計では、慎重に、型を選び、大きさや長さを検討しますね。
全て文字型なんて すっごい 設計もあるみたいですが、 普通は、様々な型が採用されます。
そして、入って来るデータが既定の種類である事をデータベースシステムが保証する訳ですね。.


ですから、
大抵のアプリでは、上記の文字数 問題が 制約違反 として、エラーを引き起こし実行を中断するケースは少ないのでしょう。
とんでもない想定外の 値 (えらく長い値) を入れるケースは そうは ありませんから。
だから、この点は、あまり、クローズアップされないのかも知れません。


しかし、やはり、いきなり、DataGridView の Column にその様なデータを打ち込んで見ると、
MaxInputLength=32767 に違反しなければ、入ってしまいます。
でも、いざ、別の Row や Column に移動しようとしても、不正な値ですから ... 。
   例 : DataBase で Nvarchar Size(Len)=5 にして、DataGridView で該当欄に "123456" と入れられますが、
       その欄から水平移動(同一行の別欄へ)は出来ても、 別行へ移動は 例外により 出来ません。 

勿論、普通の TextBox でデータバインドしても、同じ事が言えます。




さてさて、コード記述のポイント。  自動生成されたデータセット(型付データセット)が対象です。.


文字型の列なら、ソースの中で、この様に。
Me.DataGridViewTextBoxColumn1.MaxInputLength = Me.xxxDataSet.TableName.yyyColumn.MaxLength
実際には、 DataGridViewTextBoxColumn1 の .Name を分り易いものに変えて置かれるのをお勧めします。
後々、コードを見ても、どの列の事だか、さっぱり ですものね。
                          個人的には、デザイナーで、数字( 例:1 ) を DB Table Column 名( 例:yyy ) に 置き換えています。.

数値型の列は、少し、面倒です。
数字の桁数の制限で良ければ、上記の例で 右辺を 例えば = 3 ( 3 桁の数字 ) と してしまえば、簡単ですが ... 。
例えば、Int32 の制限一杯まで入力させたいとなると、 こんなに 簡単には 行きません。
イベントハンドラ Validating や DataError で、 ゴリゴリ とコードを書かないとなりません ... 。
ここで、具体的なコードを示すのは省略させて下さい。
その辺りは、また、別の機会に と言う事で ... 。     もう、ねむぅ~ ... 。 あぁ~、zzz ... 。.



0 件のコメント:

コメントを投稿