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

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

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

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

SQL Server

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

SQL

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

Q&A

解決済

1回答

3145閲覧

C#でSQLの結果をlabelに表示したい。

nao_1218s

総合スコア2

C#

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

SQL Server

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

SQL

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

0グッド

1クリップ

投稿2021/06/15 03:49

編集2021/06/15 05:16

C#でSQLの結果をlabelに表示したい。

商品表の検索表示画面を作成しています。
商品検索画面で商品名・金額を入力し検索ボタンを押すと、該当する結果が表示されるプログラムを作っています。
色々調べていると配列を作成し、その配列にSQLの結果を入れforeachでlabelに表示といった
やり方があったのですが、商品名のみ表示され金額が表示されないという結果になってしまいました。
DBではProductがnvarchar(max)、AmountがintでProducts表を作っています。
何かアドバイスいただけたら幸いです。

追記:
WindowsFormsで作成しておりOSはwindows10、VisualStudioは16.9.2、DBはMSSQL、.NET Frameworkで4.8.04084、エディションバージョンはMicrosft SQL Server Express Edition(64-bit)です。

C#

1private void button3_Click(object sender, EventArgs e) 2 { 3 //検索結果格納用 4 var resultsPro = new List<string>(); 5 var resultsAmo = new List<string>(); 6 7 8 using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ProInfo"].ConnectionString)) 9 { 10 string ProductName = textBox3.Text; 11 string stAmount = textBox4.Text; 12 int Amount = int.Parse(stAmount); 13 14 try 15 { 16 conn.Open(); 17 var cmd = conn.CreateCommand(); 18 //商品名・金額が完全一致の時 19 cmd.CommandText = "select Product,Amount from Products where Products.Product like '%" + ProductName + "%'" 20 + "and Products.Amount like '%" + Amount + "%'"; 21 22 //sqlの実行、結果を各resultに 23 using(var reader = cmd.ExecuteReader()) 24 { 25 while(reader.Read() == true) 26 { 27 resultsPro.Add((reader["Product"] as string)); 28 } 29 30 } 31 using (var reader = cmd.ExecuteReader()) 32 { 33 while (reader.Read() == true) 34 { 35 resultsAmo.Add((reader["Amount"] as string)); 36 } 37 38 } 39 40 41 } 42 catch (Exception exception) 43 { 44 Console.WriteLine(exception); 45 } 46 finally 47 { 48 conn.Close(); 49 } 50 } 51 //商品名をlabel6に 52 string resultText1 = string.Empty; 53 foreach(string item in resultsPro) 54 { 55 resultText1 += item + "\r\n"; 56 } 57 label6.Text = resultText1; 58 59 //金額をlabel7に 60 string resultText2 = string.Empty; 61 foreach (string item in resultsAmo) 62 { 63 resultText2 += item + "\r\n"; 64 } 65 label7.Text = resultText2; 66 }

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/06/15 04:52

こういう質問をするなら、必ず何を作っているか(WinForms? WPF? ASP.NET Web Forms? その他?)と開発環境(OS, Visual Studio のバージョン、DB は何かとそのバージョン、.NET Framework or Core どっちかとそのバージョン)を書こう。
nao_1218s

2021/06/15 05:01

ご指摘ありがとうございます。WindowsFormsで作成しておりOSはwindows10、VisualStudioは16.9.2、DBはMSSQL、.NET Frameworkで4.8.04084です。
BeatStar

2021/06/15 05:32 編集

そういう情報は本質問に書いてください。
退会済みユーザー

退会済みユーザー

2021/06/15 05:10 編集

上記のことは追加情報として質問欄を編集して追記願います。ここは「質問への追記・修正」を行う場所ですし、初期画面では閉じていて読まない人もいますから。 MSSQL = SQL Server ですよね? であれば、DB2 のタグは削除して SQL Server のタグをつけてください。エディション・バージョンも書いてください。(DB2 は IBM 製品です)
nao_1218s

2021/06/15 05:17

編集させていただきました。ご指摘ありがとうございます。
退会済みユーザー

退会済みユーザー

2021/06/15 05:21 編集

select クエリが変だと思うのですが。(and で良いのか? int 型のあいまい検索なんてできるのか?) SSMS を使えますか? 使えるのであれば、cmd.CommandText のクエリをデバッガで取得して、それを SSMS から投げてみてはいかがですか?
nao_1218s

2021/06/15 05:36

ご提案ありがとうございます。使えるか分かりませんが色々調べ試してみます。ただこちらの都合上PCにあまりツールをインストールするのが許されていないため使えない可能性もあります。
退会済みユーザー

退会済みユーザー

2021/06/15 05:57

上のコメントに「int 型のあいまい検索なんてできるのか?」書きましたけど、SQL Server 2012 で実際に試したらできました。 対象は文字列のはずなのでホントにそれで良いのかは疑問ですけど、とにかく結果 OK ということのようですし、質問者さんのケースでも「商品名のみ表示され」ということなので、質問者さんが使ってクエリでもレコードの取得はできているようです。 ということは、問題はその後の SqlDataReader の使い方にあるようです。
nao_1218s

2021/06/15 06:11

ウォッチでresultsPro.Addの部分を見ると実際に入力した内容とDBにあるものと一致したものが格納されているのが確認できるのですが、resultsAmoの部分ではnullが入ってしまうのでやはりこの部分が問題なのでしょうか。
退会済みユーザー

退会済みユーザー

2021/06/15 06:36 編集

resultsAmo.Add((reader["Amount"] as string)); が問題だと思います。int 型であれば as string では結果は null になるのでは? as int にしないとダメでは? あと、その前に var resultsAmo = new List<string>(); も List<int> にしないとダメなのでは?
nao_1218s

2021/06/15 06:38

as int の場合エラーで「as演算子は参照型またはnull許容型で使用してください」となり、intはnull非許容の値型ですと表示されます。
退会済みユーザー

退会済みユーザー

2021/06/15 06:44

そうですね as を使うなら int? にする必要がありますね。それで解決できると思うのですが、やり方を全体的に見直した方が良さそうです。あとで回答欄に案を書いておきます。
guest

回答1

0

ベストアンサー

SQL Server の Products テーブルの、

Amountがint

とのことですので、

resultsAmo.Add((reader["Amount"] as string)); で as 演算子の結果は null になるのが問題のようです。

上記を as int に変更して、その前の var resultsAmo = new List<string>(); も List<int?> にすることで問題を解決できると思います。

ただ、SqlDataReader を 2 回も使っているというのは無駄なので、そのあたりのやり方を見直した方が良さそうです。質問のコメント欄で「あとで回答欄に案を書いておきます」と書きましたが、それを以下に書いておきます。

実際にできることを示さないと説得力がないのですが、質問者さんの DB は使えないので、代わりに Microsoft のサンプルデータベース Northwind の Products テーブルを使ってみます。

UnitPrice 列は money 型ですが int 型と同等にあいまい検索できるようです。LIKE 句の対象は文字列のはずなのでホントにそれで良いのかは疑問ですけど、とにかく結果 OK ということのようですので、とりあえずこれで進めます。

イメージ説明

質問者さんのが質問に書いたコードと同様に文字列連結で select 文を組み立てて(ホントはパラメータ化すべきなのですが)、上の画像の WHERE 句の条件で Products テーブルからレコードを取得します。

その際、SqlDataReader を 2 回使う必要はなくて、以下のコードのように Product クラスを定義して List<Product> 型のオブジェクトとして 1 回で取得することをお勧めします。

それから、as 句を使うより、SqlDataReader クラスのメソッドとして備わっている GetInt32, GetString を使う方が良さそうです。(好みの問題かもしれませんが)

namespace ConsoleApp1 { public class Product { public int ProductID { get; set; } public string ProductName { set; get; } // UnitPrice 列は NULL 可なので ? はその対応 public decimal? UnitPrice { set; get; } } class Program { static void Main(string[] args) { string connString = "接続文字列"; string productName = "ch"; string amount = "2"; string selectQuery = "SELECT [ProductID] ,[ProductName] ,[UnitPrice] FROM [Products] " + $"WHERE [ProductName] LIKE '%{productName}%' AND [UnitPrice] LIKE '%{amount}%'"; List<Product> productList = new List<Product>(); using (var connection = new SqlConnection(connString)) { using (var command = new SqlCommand(selectQuery, connection)) { connection.Open(); using (var reader = command.ExecuteReader()) { while (reader.Read()) { var product = new Product { ProductID = reader.GetInt32(0), ProductName = reader.GetString(1), // UnitPrice 列は NULL 可なのでその対応が必要 UnitPrice = reader.IsDBNull(2) ? null : (decimal?)reader.GetDecimal(2) }; productList.Add(product); } } } } var resultsPro = new List<string>(); var resultsAmo = new List<decimal?>(); foreach (var product in productList) { resultsPro.Add(product.ProductName); resultsAmo.Add(product.UnitPrice); } } } }

Label に表示する文字列は List<Product> から直接取得して組み立てれば良いはずです。何かの理由で resultsPro, resultsAmo に取得する必要があれば上のコードの下の方のようにしてください。

結果は以下のようになります。

イメージ説明

その他、今回の問題とは直接関係ないことですが、以下の点も今後の課題として考えることをお勧めします。

(1) SQL インジェクション防止のため SQL 文はパラメータ化する(文字列連結で SQL 文を組み立てるのはダメ)

(2) Exception は catch しない。例外をなかったことにするのはいろいろマズい。

投稿2021/06/15 07:53

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

nao_1218s

2021/06/15 08:21

回答していただきありがとうございます。as intだとエラーになってしまったのでこちらもas int?で許容型にすることで全て表示することが出来ました。 まだまだ理解していない部分もあるのでご指摘いただいた課題も含め頑張っていきたいと思います。 この度はありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問