QA@IT
«回答へ戻る

回答を投稿

DataReaderのGetStringとは、引数に指定した列番号(0から始まる)の値を、DBのテーブルで文字列型の列だと仮定して取得するメソッドです。
本当の値がなんであれ、文字として取りにいきます(ToStringの様な文字化とは違います)。

しかし、実際にはSQL ServerのDecimal型だったので、文字としてみなせないものだとエラーが出ています。(エラーをみるに)。
Decimal型として取り出すか、Doubleに変換する(Double以外の数値であるため、桁が足りればDoubleに変換できます)
SQL Serverの型が.NET上なにになるかは、https://msdn.microsoft.com/ja-jp/library/cc716729(v=vs.110).aspx を参照してみてください。

(しかし、VB.NETだとGetStringをDoubleにいれようとしてるのコンパイルエラーにならないんですね)

それとは別に、問題があって。
selectの列数から、 5列分の値を取り出そうとしているように見えますが、画像の結果から現在の条件だと 2件とれるように見えます。10個の値を取ろうとすることになるのに、配列が 5つしかありません。
とりあえず、1行目だけ取り出すようにしてみます。

SQLのDecimalが .NET側でどの型になるか覚えてないですが以下の様にしてみてください。

            Try
                connection.Open()
                Dim dr As SqlDataReader = command.ExecuteReader()

---値を配列に読み込む
                Dim Count As Integer = 0
                Dim valuelist(5) As Double
                While (dr.Read())
                    valuelist(0) = Convert.ToDouble(dr(Count)) ' 変数で列インデックス指定
                    valuelist(1) = Convert.ToDouble(dr("valueB")) ' selectの列名指定
                    valuelist(2) = Convert.ToDouble(dr("valueC"))
                    valuelist(3) = Convert.ToDouble(dr(3))     ' 列インデックス指定
                    valuelist(4) = Convert.ToDouble(dr("valueE"))
                    valuelist(5) = Convert.ToDouble(dr("valueF"))
                    Exit While ' 1行分しかvaluelistのサイズが無いので。
                End While

                result = valuelist
---
                connection.Close()

            Catch ex As Exception

            End Try

drに対して文字をつかったり、変数を使ったり、数字を直接指定したりしてますが、いずれも取り出したい列を指定しています。いくつかのバリエーションでやってみました。実際はどれか1つのやり方でかまいません。
コンパイルしてないので、何かミスがあった場合はすいません。

他の指摘としては、

  • 配列よりもnew List(Of Double) と、リストに乗り換えた方がいいでしょう。
  • Usingブロックを使っているので、connection.Closeは.NETに任せても大丈夫です。
  • SqlDataReader など、ほかにもUsingブロックが使えるものがあります。
DataReaderのGetStringとは、引数に指定した列番号(0から始まる)の値を、DBのテーブルで文字列型の列だと仮定して取得するメソッドです。
本当の値がなんであれ、文字として取りにいきます(ToStringの様な文字化とは違います)。

しかし、実際にはSQL ServerのDecimal型だったので、文字としてみなせないものだとエラーが出ています。(エラーをみるに)。
Decimal型として取り出すか、Doubleに変換する(Double以外の数値であるため、桁が足りればDoubleに変換できます)
SQL Serverの型が.NET上なにになるかは、[https://msdn.microsoft.com/ja-jp/library/cc716729(v=vs.110).aspx](https://msdn.microsoft.com/ja-jp/library/cc716729(v=vs.110).aspx) を参照してみてください。

(しかし、VB.NETだとGetStringをDoubleにいれようとしてるのコンパイルエラーにならないんですね)


それとは別に、問題があって。
selectの列数から、 5列分の値を取り出そうとしているように見えますが、画像の結果から現在の条件だと 2件とれるように見えます。10個の値を取ろうとすることになるのに、配列が 5つしかありません。
とりあえず、1行目だけ取り出すようにしてみます。

SQLのDecimalが .NET側でどの型になるか覚えてないですが以下の様にしてみてください。

```vb
            Try
                connection.Open()
                Dim dr As SqlDataReader = command.ExecuteReader()

---値を配列に読み込む
                Dim Count As Integer = 0
                Dim valuelist(5) As Double
                While (dr.Read())
                    valuelist(0) = Convert.ToDouble(dr(Count)) ' 変数で列インデックス指定
                    valuelist(1) = Convert.ToDouble(dr("valueB")) ' selectの列名指定
                    valuelist(2) = Convert.ToDouble(dr("valueC"))
                    valuelist(3) = Convert.ToDouble(dr(3))     ' 列インデックス指定
                    valuelist(4) = Convert.ToDouble(dr("valueE"))
                    valuelist(5) = Convert.ToDouble(dr("valueF"))
                    Exit While ' 1行分しかvaluelistのサイズが無いので。
                End While

                result = valuelist
---
                connection.Close()

            Catch ex As Exception

            End Try
```

drに対して文字をつかったり、変数を使ったり、数字を直接指定したりしてますが、いずれも取り出したい列を指定しています。いくつかのバリエーションでやってみました。実際はどれか1つのやり方でかまいません。
コンパイルしてないので、何かミスがあった場合はすいません。

他の指摘としては、
* 配列よりも`new List(Of Double)` と、リストに乗り換えた方がいいでしょう。
* Usingブロックを使っているので、connection.Closeは.NETに任せても大丈夫です。
* SqlDataReader など、ほかにもUsingブロックが使えるものがあります。