質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

2回答

4943閲覧

SQLServerにあるデータベースの行を削除したい(C# DataSet)

Loky

総合スコア41

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

0クリップ

投稿2021/05/13 06:07

編集2021/05/13 08:31

前提・実現したいこと

SQLからデータを取り込み、dataGridViewに表示。入力フォームからデータを入力するとDataSetへ展開しSQLの方へ更新をかける。
というアプリケーションを勉強がてら作成しています。
イメージ:SQL⇔DataSet(DataTable)⇔dataGridView⇔入力フォーム

このアプリケーションでdataGridViewにチェックボックスを用意してあげてチェックを付けたデータに対し、削除ボタンを押下するとデータベースから該当データ(行?レコード?)を削除する機能を持たせようとしています。
SQLからデータベースをDataSetに展開し、DataSetにあるDataTableの行を削除してからDataSetでデータベースを更新かけてあげればいいと思っているのですが、DataSetの行の削除段階でエラーが発生し、苦戦しています。
解決方法をご教示願えませんでしょうか。

アプリケーション側ではGUIをこのような形で作成しています。
イメージ説明

発生している問題・エラーメッセージ

試験的にdataGridViewの4行目(インデックスにすると3)を削除しようと実行してみましたが、下記エラーが発生しました。 エラーメッセージ:System.IndexOutOfRangeException: 'There is no row at position 3.' 該当コード:form_Main.DaSet.Tables["Test_Table1"].Rows.RemoveAt(r);

該当のソースコード

C#

1 private void button_rowRemove_Click(object sender, EventArgs e) 2 { 3 //Form_Mainのインスタンス作成 4 Form_Main form_Main = new Form_Main(); 5 6 form_Main.connection = new SqlConnection(Properties.Settings.Default.sqlServer); 7 form_Main.connection.Open(); 8 9 //行削除用コマンド 10 form_Main.DelCmd.Connection = form_Main.connection; 11 form_Main.DelCmd.CommandType = CommandType.Text; 12 form_Main.DelCmd.CommandText = "DELETE FROM Test_Table1 WHERE 選択 = @選択"; 13 14 //データセットに取得するための設定 15 form_Main.Cmd.Connection = form_Main.connection; 16 form_Main.Cmd.CommandType = CommandType.Text; 17 form_Main.Cmd.CommandText = "SELECT * FROM Test_Table1"; 18 form_Main.Sdt.SelectCommand = form_Main.Cmd; 19 20 form_Main.DaSet.Clear(); 21 form_Main.Sdt.Fill(form_Main.DaSet, "Test_Table1"); 22 23 //チェックボックスがチェックされている行を削除(複数対応) 24 for (int r = 0; r < dataGridView1.RowCount; r++) 25 { 26 if ((bool)dataGridView1.Rows[r].Cells[0].Value) 27 { 28 form_Main.DaSet.Tables["Test_Table1"].Rows.RemoveAt(r); 29 30 form_Main.DelCmd.Parameters.Clear(); 31 form_Main.DelCmd.Parameters.Add("@選択", SqlDbType.Bit, 1, "選択"); 32 form_Main.Sdt.DeleteCommand = form_Main.DelCmd; 33 34 form_Main.Apply(); 35 36 //dataGridView1.Rows.RemoveAt(r); 37 r--; 38 } 39 } 40 41 //実行結果をdataDridViewに表示 42 dataGridView1.Columns.Clear(); 43 dataGridView1.DataSource = null; 44 dataGridView1.DataSource = form_Main.DaSet.Tables["Test_Table1"]; 45 } 46

試したこと

たいしたことは試していないのですが、
form_Main.DaSet.Tables["Test_Table1"].Rows.RemoveAt(r);
をDelete()、AcceptChanges()メソッドに変更してみました。
同様のエラーが発生するため、行指定が誤っているものかと考えてますがいかがでしょうか。。
また、DataSetに取得したデータが誤っているのかと考え行・列指定でデータを出力したところ、狙ったデータが取得できていることは確認できました。

補足情報(FW/ツールのバージョンなど)

使用ツール:VisualStudio2019
ターゲットフレームワーク:.NET Core3.1
※ターゲットフレームワークについては特に拘りがありませんので、.NET Frameworkでの解決方法がござざいましたらそちらでも問題ありません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/05/13 22:05 編集

Core は必須ですか? .NET Framework 版ならデザイナが使えるので、SQL Server のテーブルのレコードの DataGridView への一覧表示・編集・更新を行うアプリは容易に作成できますが。
Loky

2021/05/13 08:20

初っ端のソリューション作成時にターゲットをCoreにしてしまって.NET Frameworkへの移行は全く考えていませんでした。 参考までに.NET Frameworkですとどういったコードになるかご教示いただくことは可能でしょうか。
退会済みユーザー

退会済みユーザー

2021/05/13 08:29 編集

.NET Framework 版でもよいということなら質問を編集してその旨追記してください。 「どういったコードになるか」を書くにもそれなりの時間と労力がいるのです。「参考までに」程度の話であれば書く気力は沸いてこないのです。
Loky

2021/05/13 08:33

質問は補足情報へ記載させていただきましたが、認識問題ありませんでしょうか。 >「どういったコードになるか」を書くにもそれなりの時間と労力がいるのです。 仰る通りですね。。こちらに齟齬がありましたこと申し訳ございませんでした。
guest

回答2

0

ベストアンサー

forループの、テスト時(4行表示で最終行削除)の場合の動作ですが、以下のようになるかと。

rが0,1,2の時、if条件がfalseなので、何もしない。
rが3の時、if条件がtrueなので、中の処理へ。
該当レコードの削除を行い、Apply()。
この時、dataGridView1の中身は、更新されていないのでは?
その後、rを戻す。
次のループとして、rが3になり、同様にif条件がtrueなので、中の処理へ。
該当レコードがないので、エラー。

解決策は、forループを逆にし、処理内でループカウンタを変更しない事。
配列などにおいて、forループで削除する場合は、逆順でやらないと正常に動作しないことが多いので、逆順処理がセオリーになっています。

なお、上記に記載の動作は未検証です。
デバッグなどで、実際のrの変遷と、処理の実際をご確認ください。

投稿2021/05/14 01:07

YT0014

総合スコア1750

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Loky

2021/05/14 01:52

ご回答ありがとうございます。 配列におけるfor文処理のセオリー理解できていませんでした。。また一つ勉強させてもらいました。 仰る通りにコードを修正しデバッグモードにて確認します。 ありがとうございました。
YT0014

2021/05/14 01:56

エラー時の状態の確認が先ですので、コードを修正せずに、デバックモードにてご確認ください。 不具合の修正は、「原因の確認」をしてから、「修正」です。 原因が確定しないままの修正は、修正されたのか、隠れただけなのか、不確かな状態になります。
Loky

2021/05/14 02:02

失礼しました。 そのようにいたします。
Loky

2021/05/14 04:11

確認しました。 rを戻す操作によってr=3の時の処理が二回発生してしまい、二回目の処理時に「その行はもうない」というエラーが発生していました。 原因はYT0014さんの仰る通りでございました。 逆順処理では発生しないことも確認できました。 ご助言ありがとうございました。
guest

0

ターゲットフレームワークについては特に拘りがありませんので、.NET Frameworkでの解決方法がござざいましたらそちらでも問題ありません。

・・・ということですので、.NET Framework 版の Windows Forms アプリをベースに書きます。(Core 版では下の画像のドラッグ&ドロップが現状できないです。そのうち改善されるのかもしれませんが)

データソースが SQL Server などのデータベースのテーブルで、そのレコード一覧を DataGridView に表示し、ユーザーが DataGridView を見て編集した結果を、元のデータベースのテーブルに反映させるというようなことがやりたいこととと想像してますが、そうであれば一度 Visual Studio のウィザードを使って定番の構成のアプリを作ってみることをお勧めします。

DB が SQL Server の場合ですが、以下のチュートリアル、

チュートリアル : データベースへのデータの保存 (単一テーブル)
https://docs.microsoft.com/ja-jp/previous-versions/0f92s97z(v=vs.120)

10 行でズバリ !! 非接続型のデータ アクセス
https://github.com/microsoftarchive/msdn-code-gallery-community-0-9-non-alphabetic/tree/master/10%20%E8%A1%8C%E3%81%A7%E3%82%BA%E3%83%90%E3%83%AA%20!!%20%E9%9D%9E%E6%8E%A5%E7%B6%9A%E5%9E%8B%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%20%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%20%28ADO.NET%29%20%28VB%29

新しいデータ ソースの追加
https://docs.microsoft.com/ja-jp/visualstudio/data-tools/add-new-data-sources?view=vs-2019

・・・のように Visual Studio のデータソース構成ウィザードを利用して型付 DataSet + TableAdapter を作って、それを利用してアプリを作ると、

DataGridview ⇔ BindingSource / BindingNavigator ⇔ DataSet / DataTable ⇔ DataAdapter ⇔ SQL Server

という構造のアプリが、ほとんど自分でコードを書くこと無しに作れます。

それにどういうメリットがあるかと言うと、以下の記事の「非接続型のデータ更新」のセクションの図1と図2を見てください。文章は読まなくてもいいので図だけ見てください。

DB 設計者のための明解 ADO.NET 第 1 回
https://docs.microsoft.com/ja-jp/previous-versions/cc482903(v=msdn.10)

図2の DataSet 左側に BindingSource / BindingNavigator 経由で DataGridView が接続されていると思ってください。

ユーザーが DataGridView を操作(行の削除・追加・訂正)した結果は図1にあるように DataSet / DataTable に反映されます。ユーザーの編集操作が終わったら Update メソッドで図1の編集結果が一度に DB に反映されます。そういうアプリが簡単に作れるようにできているのです。

上に紹介した後者のチュートリアルは 2 つのテーブルを階層更新するために少々複雑になっていますが、単一テーブルですと前者のチュートリアルのように非常に簡単で、型付 DataSet + TableAdapter を作って、DataGridView に表示したいならドロップダウンでそれを選んでから、下の画像のようにドラッグ&ドロップすれば、

イメージ説明

以下のようなアプリが 5 分もかからず作れるはずです。

イメージ説明

是非一度お試しください。

投稿2021/05/13 08:58

編集2021/05/13 22:09
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Loky

2021/05/13 09:05

迅速なご対応ありがとうございます。 迅速にご対応いただいたところ申し訳ございませんが、明日ご回答を読ませていただき、実現できるよう挑戦させていただきます。 お手を煩わせて申し訳ありませんが、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問