- PR -

◆データベースのテーブルから指定した複数のレコードを削除したい。

投稿者投稿内容
こあら
大ベテラン
会議室デビュー日: 2007/06/26
投稿数: 157
投稿日時: 2008-08-12 12:17
引用:

One.netさんの書き込み (2008-08-12 11:52) より:
こあらさん、ありがとうございます。
IndexOfメソッドは NN文字列の中にパラメータ指定した文字列存在チェック(又は最初に見つかった位置)
に使うもので数字(NN)には使用できない思っていましたし、配列変数(NN())の全てをチェックできないと
思っています。

また実際のご指摘のコードをテストしますと「この引数の数を受け付ける"IndexOf"がないため
オーバーロードの解決に失敗しました」と表示されビルドが失敗します。
何か間違ってテストしているのでしょうか。



そうですか。indexOfではチェックできないのですね。
間違った書き込みで惑わせてしまい大変申し訳ありませんでした。
One.netさんのコードが最適解でした。
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-08-12 13:09
Integer配列のかわりに、List(Of Integer) を使ってみました。

コード:
        Dim NN As New List(Of Integer)
        NN.AddRange(New Integer() {2, 4, 6, 8, 10, 12})
        For Each dr As DataRow In DataSet1.table1.Rows
            Dim ZZ As Integer = CInt(dr("番号"))
            If NN.Contains(ZZ) Then
                dr.Delete()
            End If
        Next

One.net
大ベテラン
会議室デビュー日: 2008/03/01
投稿数: 202
投稿日時: 2008-08-12 13:48
こあらさん、ありがとうございました。
何とか皆様のご指導で正常に動作できました。

rainさん、ありがとうございます。
また私には使ったことのない List(Of Integer) について少し勉強してみます。
ただ今回は「指定した複数のレコードを削除したい」が主題なので、For〜Next文の
使用順序を逆にすることで解決いたしました。

諸先輩からのご指導感謝します。ありがとうございました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-08-18 22:20
引用:

One.netさんの書き込み (2008-08-11 15:48) より:
table1 の指定した複数のレコードを削除したく、次のコードを実行しましたが
「削除された行を通して、その行の情報にアクセスすることはできません。」と
エラーメッセージが表示されてしまいます。
(略)
このことは i = 0 でDataRowオブジェクトにDeleteマークを付けてから i = 1 で
再度参照しようとしたのでエラーが発生するのだろうと考え


その解釈で正しいです。


考え方のバリエーションその1。
 SQL での DELETE 文発行1回でやるなら、
DELETE FROM table WHERE "番号" IN (2, 4, 6, 8, 10, 12)
のような感じ。一意にする情報を覚えて、DataTable からは Remove しちゃって、DELETE 1回にした方が、ラウンドトリップは確実に減る。


考え方のバリエーションその2。
 DataTable を編集して、ぐるぐる回したいなら、ループする順番を変えればいい。
コード:
Me.table1TableAdapter.Fill(Me.DataSet1.table1)
Dim NN(10) As Integer
NN(0) = 2 : NN(1) = 4 : NN(2) = 6
NN(3) = 8 : NN(4) = 10 : NN(5) = 12
For row As Integer = 0 To DataSet1.table1.Rows.Count
    DataRow dr = DataSet1.table1(row)
    For Each n As Integer In NN
        If CInt(dr("番号")) = n Then
            dr.Delete()
            Exit For
        End If
    Next
Next
'--更新処理
Me.Validate()
Me.table1BindingSource.EndEdit()
table1TableAdapter.Update(Me.DataSet1.table1)




考え方のバリエーションその3。
 ループの順番を元のまま、エラーを無くしたいなら、RowState をチェックする。
コード:
Me.table1TableAdapter.Fill(Me.DataSet1.table1)
Dim NN(10) As Integer
NN(0) = 2 : NN(1) = 4 : NN(2) = 6
NN(3) = 8 : NN(4) = 10 : NN(5) = 12
For Each n As Integer In NN
    For row As Integer = 0 To DataSet1.table1.Rows.Count
        DataRow dr = DataSet1.table1(row)
        If dr.RowState == RowState.UnChanged _
        AndAlso CInt(dr("番号")) = n Then
            dr.Delete()
        End If
    Next
Next
'--更新処理
Me.Validate()
Me.table1BindingSource.EndEdit()
table1TableAdapter.Update(Me.DataSet1.table1)


 NN は、ループ中は固定したコレクションなので、For Each 文を使ってかまいません。
 Delete メソッドは、その行を「削除」とマークするだけのようですが、RowState.Added な行はコレクションから取り除くため、コレクションを変更してしまう可能性があります。このため、For Each 文は使えません。


考え方の基本。
 ループの順番を変えるのは、より早くループが終わることを考えてみるといいでしょう。テーブルに、行が100あるとします。元の順番なら、必ず600回、If 文を通ります。しかし、順番を入れ替えると、行を参照する100回は変わらないけど、「この配列にあるか?」のチェックで、配列内にあればそれ以降のチェックはしなくなります。削除対象の行が存在しないなら600回通るけど、すべての行が NN(0) にマッチするなら、100回しか通らないことになるというわけです。
 文章で書いてもわからなかったら、各行でそれぞれの変数がいくらになるか書き出して、確認してみるといいでしょう。(←これ、初心者のうちは重要)


開発の基本。
引用:

(2008-08-12 11:52) より:
IndexOfメソッドは NN文字列の中にパラメータ指定した文字列存在チェック(又は最初に見つかった位置)に使うもので数字(NN)には使用できない思っていましたし、配列変数(NN())の全てをチェックできないと思っています。

また実際のご指摘のコードをテストしますと「この引数の数を受け付ける"IndexOf"がないためオーバーロードの解決に失敗しました」と表示されビルドが失敗します。


 で、調べました?→Array..::.IndexOf メソッド<microsoft.com>
 引数1つを受け取る IndexOf メソッドがないだけです。じゃぁ、引数の数が合うものを探せばいい。
 今回の用にあうのは、これ、「IndexOf(Array, Object)」。ループがひとつ少なくなります。
コード:
Me.table1TableAdapter.Fill(Me.DataSet1.table1)
Dim NN(10) As Integer
NN(0) = 2 : NN(1) = 4 : NN(2) = 6
NN(3) = 8 : NN(4) = 10 : NN(5) = 12
For row As Integer = 0 To DataSet1.table1.Rows.Count
    DataRow dr = DataSet1.table1(row)
    If Array.IndexOf(NN, CInt(dr("番号"))) > -1 Then
        dr.Delete()
    End If
Next
'--更新処理
Me.Validate()
Me.table1BindingSource.EndEdit()
table1TableAdapter.Update(Me.DataSet1.table1)


なお、コードはすべて直打ち未検証。
One.net
大ベテラン
会議室デビュー日: 2008/03/01
投稿数: 202
投稿日時: 2008-08-19 07:25
Jittaさん、ありがとうございました。
レコードの削除だけでもこれほどの方法があるのですね。特に「考え方のバリエーションその3。」は
RowState をチェックとCInt(dr("番号"))のチェックをAndAlsoで選択すればDeleteマークが付いた
レコードの参照がなくなることは勉強になりました。
また、少し難しいようですが以下のことも勉強します。
引用:

引用:

(2008-08-12 11:52) より:
IndexOfメソッドは NN文字列の中にパラメータ指定した文字列存在チェック(又は最初に見つかった位置)に使うもので数字(NN)には使用できない思っていましたし、配列変数(NN())の全てをチェックできないと思っています。

また実際のご指摘のコードをテストしますと「この引数の数を受け付ける"IndexOf"がないためオーバーロードの解決に失敗しました」と表示されビルドが失敗します。


 で、調べました?→Array..::.IndexOf メソッド<microsoft.com>
 引数1つを受け取る IndexOf メソッドがないだけです。じゃぁ、引数の数が合うものを探せばいい。


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

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