- PR -

空文字列不許可のフィールドにデータをNull値にして保存したい

投稿者投稿内容
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-09 18:07
テキストボックスのBindingオブジェクトの
NullValueプロパティ(既定はNothing)にString.Emptyを設定してはどうでしょう?

コード:

Me.Fldテスト2TextBox.DataBindings(0).NullValue = String.Empty



#コード追加しました

[ メッセージ編集済み 編集者: KI 編集日時 2007-02-09 18:10 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-02-09 23:10
引用:

goo〜glenさんの書き込み (2007-02-09 17:09) より:

Updateは、上記のような処理です。


つまり、自動生成に任せてますよ、、、ってことですか?
そりゃ、失敗するだろうな。NULL を = で比較することは出来ませんから。
_________________
goo〜glen
会議室デビュー日: 2007/02/04
投稿数: 14
投稿日時: 2007-02-10 00:21
KIさん、ありがとうございます。無事解決できました。

教えていただいたコードをLoadイベントに入れたところエラーなく保存できました。
また、コンボボックスの修正(クリア)もエラーなく保存できました。
コード:

Private Sub Form1_Load(ByVal sender As System.Object, ・・・
Me.Fldテスト3ComboBox.Items.Add("aaa")
Me.Fldテスト3ComboBox.Items.Add("bbb")

Me.TblテストTableAdapter.Fill(Me.TestDataSet.tblテスト)

Me.Fldテスト2TextBox.DataBindings(0).NullValue = String.Empty
Me.Fldテスト3ComboBox.DataBindings(0).NullValue = String.Empty
End Sub


ところで、
「Binding.NullValue プロパティ」や「Binding クラス」等のヘルプを探したのですが、
「DataBindings(0).NullValue」のような記述が見つかりませんでした。
このコードの中の「(0)」は、何を指すのでしょう?

また、
> NullValueプロパティ(既定はNothing)にString.Emptyを設定してはどうでしょう?
と言うのは、↓に関することでしょうか?
//////////////////////////////////////////////////////////////////////////////////////
[ヘルプより]
プロパティ値
データ ソースに DBNull 値が格納されている場合にコントロール プロパティとして設定される Object。既定値は null 参照 (Visual Basic では Nothing) です。

解説
null 参照 (Visual Basic では Nothing) に設定されている場合、NullValue プロパティは無視されます。

コントロール プロパティが NullValue のオブジェクトに設定されている場合、データ ソースに null 値が追加されます。NullValue が文字列値に設定されている場合、比較は大文字と小文字を区別しません。
//////////////////////////////////////////////////////////////////////////////////////
「コントロール プロパティとして設定される Object」として、「String.Empty」を設定したと?
でも、「String.Empty」=「長さ 0 の文字列 ""」?
「コントロール プロパティが NullValue のオブジェクトに設定されている場合、データ ソースに null 値が追加されます。」?
「String.Empty」を設定したから、「null 値が追加されます。」なのかな?

後日でも、もしお時間が許すなら、少しご解説いただけると助かります。

本当にありがとうございました。



Jittaさん、無事解決できました。

今回は、テストを兼ねて、自動生成のUpdateCommandを利用しましたが、ExecuteNonQuery()
による更新も検討しておりました。
と言っても、VB歴数ヶ月ですから、前途多難ですが、、

NULLの比較とは?  IsDBNull(xxx.Textとか) のことでしょうか?

また機会がありましたら、よろしくお願いします。

[ メッセージ編集済み 編集者: goo〜glen 編集日時 2007-02-10 00:25 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-02-10 00:33
引用:

goo〜glenさんの書き込み (2007-02-10 00:21) より:
KIさん、ありがとうございます。無事解決できました。


そっちだったか。。。

引用:

NULLの比較とは?  IsDBNull(xxx.Textとか) のことでしょうか?

また機会がありましたら、よろしくお願いします。


 NULL は、= で比較できないんですよ。自動生成ということは、楽観的同時実行制御が入って、
UPDATE table SET column = value WHERE column = oldValue
という SQL 文を実行しようとするはず。ここで、oldValue が NULL だと、
WHERE column(NULL) = NULL
は、FALSE になります(少なくとも、SQL Server とか Oracle の場合)。

それで更新できないんじゃないかと思ったのがひとつ。


 あと、「エラーを出す」とは書いてあるけど、そのエラーを出すのは何なのか(プログラムなのか、Access なのか)が書いてないので、何が悪いのか、判断がつかなかった。
 さらに、どうもプログラムや設定をいろいろ変えているようなのに、それぞれの設定と結果が関連づけられていないので、何でどのエラーになっているか、いまいちわからなかった。
_________________
goo〜glen
会議室デビュー日: 2007/02/04
投稿数: 14
投稿日時: 2007-02-10 13:07
Jittaさん、ありがとうございます。大変参考になりました。

>  NULL は、= で比較できないんですよ。自動生成ということは、楽観的同時実行制御が入って、
> UPDATE table SET column = value WHERE column = oldValue
> という SQL 文を実行しようとするはず。ここで、oldValue が NULL だと、
> WHERE column(NULL) = NULL
> は、FALSE になります(少なくとも、SQL Server とか Oracle の場合)。

このご回答で数週間前に悩んでいた事が見事解決しました。
Accessも同様にFalseでエラーになると思われます。
"同時実行違反 : UpdateCommand によって、処理予定の 1 レコードのうち 0 件が処理されました。"


UpdateCommandが自動生成されないTableAdapterに、自作のUpdateCommand(自動生成される
楽観的同時実行の真似事をして、クエリビルダの全てのフィールド(項目)のフィルタ欄に
「= ?」を入れたUpdateCommandです。)を作成してUpdate()を試みると、ある特定のデータ
で更新エラーになるのです。

その特定のデータとは、あるフィールドにNullを含むデータだったのです。
もちろん、データのRowStateをModifiedにするための更新は、そのフィールドで行っている訳ではありません。
また、そのフィールドがNullでなく、例えば「aaa」→「Null」のような更新では、エラーが発生しません。
そして、そのフィールドのフィルタ欄の「= ?」を外すと、Update()が成功するのです。

当時、自分なりに推察したものは、
プログラム?(Access?)が「DataTableのOriginalバージョンと元のデータベースのデータが違う」と
判断しているのではないか?
それも、元の値が「Null」だと誤判断するのではないか?
と言うものでした。

自分が今、AccessシステムからVB2005+Accessへの移行を検討しているものは、非楽観的同時実行でも
構わないもの(と言うより同時実行の可能性が限りなく少ない)でしたので、当時、
要注意事項として片付けていました。
とは言え、今回の一連の質問の中でも、VB2005のWindowsForm?(DataTable?)に読み込んだNullは、
「何かに変化?しているのか?」と気になっていました。


勉強になりました。
またよろしくお願いします。ありがとうございました。

[ メッセージ編集済み 編集者: goo〜glen 編集日時 2007-02-10 13:10 ]

[ メッセージ編集済み 編集者: goo〜glen 編集日時 2007-02-10 13:14 ]
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-10 17:31
引用:

「Binding.NullValue プロパティ」や「Binding クラス」等のヘルプを探したのですが、
「DataBindings(0).NullValue」のような記述が見つかりませんでした。
このコードの中の「(0)」は、何を指すのでしょう?



ControlBindingsCollection.Item プロパティ
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.controlbindingscollection.item(VS.80).aspx

Control.DataBindingsはControlBindingsCollectionというコレクションクラスで、
そのデフォルトのプロパティを使用しています。
つまりコレクションの先頭の要素という意味になります。
でもよく考えたら、0番目と書くのは少し気持ち悪いですので、
バインドされているプロパティ名を使って取得する方がいいですね。

コード:
Me.Fldテスト2TextBox.DataBindings("Text").NullValue = String.Empty



引用:

「コントロール プロパティとして設定される Object」として、「String.Empty」を設定したと?
でも、「String.Empty」=「長さ 0 の文字列 ""」?
「コントロール プロパティが NullValue のオブジェクトに設定されている場合、データ ソースに null 値が追加されます。」?
「String.Empty」を設定したから、「null 値が追加されます。」なのかな?



まず、バインディングの仕組みを理解して頂く必要があります。
自動生成されるのであまり意識されていないのかと思いますが、
デザイナが自動生成したコードの中で、DataBindings.Addを呼び出して
新しいBindingを追加している部分があるはずです。
そこで、TextBoxのTextプロパティ(これが「コントロール プロパティ」)と
データソースの列の値(これが「データソース」)を指定しているはずです。
これにより、コントロールのプロパティが変更されれば
それがデータソースに反映されますし、逆にデータソースの値が変更されれば
コントロールのプロパティも変更されます。これがバインドです。
ですからユーザーがテキストボックスの中身を書き換えると、
Textプロパティが変更されますのでデータソース列の値が更新されるのです。

NullValueはコントロール→データソースに値を反映するための
オプションのようなものです。
TextBoxの値を変更したときに、それがNullValueに設定されている値と等しければ、
変更されたTextBoxの値ではなく、DBNullが設定されます。
極端な話、NullValueに "ABC" とか設定すれば、
テキストボックスにABCと入力して更新するとDBNullが入るようになるはずです。

バインディングに関しては、こんな所が参考になるかと思います。

http://support.microsoft.com/kb/313640/ja
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-02-10 17:58
すみません。少し訂正します。
NullValueプロパティはコントロール→データソースへの反映のオプションではなく、
データソース→コントロールの反映にも影響します。
例えばデータソースがDBNullのときに、Nullであることがわかるような文字列を
表示した場合などにも使用します。

http://www.microsoft.com/japan/msdn/net/winforms/wfbindp1.aspx
goo〜glen
会議室デビュー日: 2007/02/04
投稿数: 14
投稿日時: 2007-02-10 22:55
KIさん、解説ありがとうございます。
大変勉強になりました。

ControlBindingsCollection クラスのメンバであるControlBindingsCollection.Item プロパティ
そして、BindingsCollection.Item プロパティ・・・
・・・似たようなページを行き来していて、混乱していますが、、、
コード:
Private Sub PrintBindingInfo()
   Dim bc As BindingsCollection = Fldテスト2TextBox.DataBindings
   Dim i As Integer 
   For i = 0 to bc.Count - 1
      Console.WriteLine(bc(i).BindingMemberInfo.BindingMember)
   Next i
End Sub


たぶん、↑を試せば、最初に"Text"が表示されるのでしょうね。
(※ 今日は、手元にVBがないため、テストできません。)

また、「NullValue」に「String.Empty(長さ 0 の文字列)」を設定したことは、
コントロールが「長さ 0 の文字列」なら、データソース(DataTable)にNullを渡すと言うことですね。
そして、その逆も。。!?
(あれ? こっちはちょっと微妙かな? 見せかけてるだけかな? 「長さ 0 の文字列」かな?)
> http://www.microsoft.com/japan/msdn/net/winforms/wfbindp1.aspx
ご紹介いただいたページ、大変参考になりました。
少し前には、「VB中学校」や書籍を参考に、手動のバインドや書式設定(FormatとParse)は、試していたの
ですが、、、
データバインドって(データバインドも)奥が深いですね。

もう少し勉強してみます。
本当は、まだまだ謎があるのですが。。。
また機会があれば教えてください。ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)