- PR -

DataView.Delete メソッドで最後の2レコードが一気に削除される

1
投稿者投稿内容
まったけ
会議室デビュー日: 2006/09/08
投稿数: 13
投稿日時: 2006-12-21 18:46
訳の分からない現象に悩んでいます(;_;)
下記のコードを実行すると、最後の WriteLine で0件と表示されてしまいます。
これは仕様なのでしょうか??


Dim dt As New DataTable
dt.Columns.Add( "Clm1", Type.GetType( "System.String" ))

Dim dv As DataView = New DataView( dt )
dv.AddNew()
dv.AddNew()
dv.AddNew()

Debug.WriteLine( dv.Count.ToString()) '3件
dv( 0 ).Delete()
Debug.WriteLine( dv.Count.ToString()) '2件
dv( 0 ).Delete()
Debug.WriteLine( dv.Count.ToString()) '0件!!!?



■環境
WindowsXP
VisualStudio2005 の VB2005
Access
ぬし
会議室デビュー日: 2002/04/08
投稿数: 829
投稿日時: 2006-12-22 06:33
レコードの追加・削除は
DataViewではなく、
DataTableにすべきでは?
_________________
ASP.NET+Ajaxサンプル集 | JavaScript+Ajaxサンプル集
まったけ
会議室デビュー日: 2006/09/08
投稿数: 13
投稿日時: 2006-12-22 10:11
Access 様
アドバイスありがとうございます。

独自のグリッドを作成しています。
おっしゃるとおり、当初は DataTable に対して行を追加するように考えていました。
グリッドに表示するときは(ユーザーが任意の列でソート可能とするため)DataView
を経由して表示しているのですが、DataTable.NewRow をすると DataView.Sort の
状態が即反映されてしまい、NewRow したばかりの空行を見失ってしまう(NULL 値
なので DataView では先頭または末尾にくる)のです。

よって DataView 上で実装せざるを得ないというわけです。
うまく伝わりましたでしょうか?

※グリッドはインライン編集タイプです。編集行を離れても自動的なコミットは行わ
ず、親ウィンドウ上にある[更新実行]ボタンで一気に変更を反映させるという設計で
す。
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2006-12-22 10:28
個人的には Access さんと同意で、DataView は DataTable をフィルタリングや
ソートしたものを表すと思っているので(テーブルとビューだから)、DataView そのもの
に追加したりはやらないですね。

引用:

まったけさんの書き込み (2006-12-22 10:11) より:

グリッドに表示するときは(ユーザーが任意の列でソート可能とするため)DataView
を経由して表示しているのですが、DataTable.NewRow をすると DataView.Sort の
状態が即反映されてしまい、NewRow したばかりの空行を見失ってしまう(NULL 値
なので DataView では先頭または末尾にくる)のです。


この場合はこうしたらどうでしょう(例によってC#でスイマセン)。

コード:

    DataRow newRow = dt.NewRow();
    newRow["Clm1"] = "いやんバカンス";
    dt.Rows.Add(newRow);

    Debug.WriteLine(dv.Count.ToString());


MSDN で DataTable.NewRow() のリファレンスを見てみたらこう書いてありました。
と思ったら、DataView.AddNew() でも戻り値が取れるので、それに対して操作す
れば空行を見失うということはないような気がしますね。前述の通り DataView よりも
DataTable を操作する派(どんな派閥だ)なので私はやりませんが。
_________________
ぽぴ王子@わんくま同盟
ぽぴ王子の人生プログラミング中 / ぽぴンち。
まったけ
会議室デビュー日: 2006/09/08
投稿数: 13
投稿日時: 2006-12-22 11:32
ぽぴ王子 様
コードまで提示していただき、ありがとうございます。

引用:

MSDN で DataTable.NewRow() のリファレンスを見てみたらこう書いてありました。
と思ったら、DataView.AddNew() でも戻り値が取れるので、それに対して操作す
れば空行を見失うということはないような気がしますね。



私の「見失う」の表現が悪かったです。ユーザーが見失う、の意です。
空行のオブジェクトは確かにつかんでいます。

このグリッドでは、ユーザーが好きな位置に行を挿入できるようにしています。
データベーステーブルという概念上、そんなことは無意味なのは承知してお
りますが、ユーザーから見た場合、
「この行位置に空行を挿入して、前後の行の内容を見ながらマスタ登録したい」
というような場合があります。既存レコードの値をちょっとだけ変えた新しい
レコードを登録するような場合に重宝されます。

よって、挿入した空行が DataView.Sort プロパティの影響を受けてしまうのを
防ぐ必要があったのです。


話の内容がグリッドの設計内容になってきたので、ここで戻させていただきます。

DataTable に対して行追加/行削除をすべきだというセオリーはちょっと置いて
おきまして、、。

DataView に対する行追加/行削除は、そんなに信頼性がないのでしょうか?
私が先に挙げたコードの現象が、DataView のバグなのか、私が勘違いをしている
のかの切り分けができなくて困っています。
(こんな単純なバグはありえないと思うので、私の勘違いの線が濃いと思ってい
ます)

どこがいけないのか、ご指摘していただけると助かります。<(_ _)>
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2006-12-22 12:37
> DataView に対する行追加/行削除は、そんなに信頼性がないのでしょうか?
ちょこっとだけ調べてみましたが、DataViewの行追加/削除は、少し変わったことをしているようです。
まず、行追加の一回目では、ソースとなるDataTableへの行追加は行っていません。
2回目以降は、"前回追加した行"をソースDataTableへ追加しています。

私もまったけさんが最初に提示したコードを試してみましたが、同様の現象が発生しました。これは普通に考えておかしな挙動ですね。
また、以下のコードを試してみてください。このコードだとうまく削除が行われます。しかし、dt.Rows.Countとdv.Countをウォッチ式に追加して1ステップ実行してみるとわかりますが、やはり変わった挙動をします。

コード:
Dim dt As New DataTable
dt.Columns.Add("Clm1", Type.GetType("System.String"))

Dim dv As DataView = New DataView(dt)
dv.AddNew()
dv.AddNew()
dv.AddNew()

Debug.WriteLine(dv.Count.ToString())
dv(dv.Count - 1).Delete()
Debug.WriteLine(dv.Count.ToString())
dv(dv.Count - 1).Delete()
Debug.WriteLine(dv.Count.ToString())
dv(dv.Count - 1).Delete()
Debug.WriteLine(dv.Count.ToString())



ということで、DataViewでの追加/削除はあまりお勧めできないですね。
まったけ
会議室デビュー日: 2006/09/08
投稿数: 13
投稿日時: 2006-12-22 12:59
よこけん 様
調べていただきましてありがとうございます。

DataView の最後尾から削除していくと、確かに思い通りの動作をしました。
そして、重大なことに気がつきました。

DataView.AddNew を実行すると、直前に AddNew したレコードは自動的に
コミット(DataTable に反映)されるのですね。内部的に DataRowView.EndEdit
が行われているようですね。気がつきませんでした。

大きなヒントをいただきました。本当にありがとうございます。
スッキリしました。(そして再設計...(;_;))
1

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