- 締切済み
VB.NET DataReaderが開かれている
おはようございます。 今回はVB.NETについて質問させてください。 【開発環境】 ・VB.NET(Visual Studio2010) ・PostgreSQL8.3 ・WindowsXP 【質問内容】 ある一定の操作をすると、 『この Command に関連付けられている DataReader が既に開かれています。このコマンドを最初に閉じる必要があります』 とエラーが出てしまい、例外で落ちてしまいます。 【落ちる原因の操作】 1.メインフレームを起動 2.親品番マスタから取得した親品番一覧を表示しているListViewの1件をダブルクリック 3.親品番に紐付いている子品番を品番テーブルから取得 4.表示内容の切り替えラジオボタンを全て⇒図面ありに変更 5.表示内容の切り替えラジオボタンを図面あり⇒全てに変更 6.表示内容の切り替えラジオボタンを全て⇒図面ありに変更 7.表示内容の切り替えラジオボタンを図面あり⇒全てに変更←ここで先ほどの例外が発生する。 【該当部分のソース】 Private Sub ArticleTableUpdate(ByVal sParents As String) Dim articleResult As Odbc.OdbcDataReader ' 品番テーブル用 Dim articleSql As String Dim zumenSql As String Dim sChild As String Dim articleCount As Integer Dim zumenCount As Integer Dim zumenFlag As String ' 品番テーブルからデータを取得するSQLを作成 articleSql = "SELECT * FROM ""ARTICLE_TBL"" WHERE ""P_ARTICLE_NUMBER"" = '" + sParents + "'" Debug.WriteLine("【ArticleTableUpdate】 品番テーブルからデータを取得SQL:" + articleSql) ODBCCommand.CommandText = articleSql ' 品番テーブルから該当の親品番のデータ件数を取得 'articleCount = ODBCCommand.ExecuteNonQuery() ' 品番テーブルに該当の親品番のデータが存在するか 'If articleCount = 0 Then 'Exit Sub 'End If ' 品番テーブルから該当の親品番のデータを取得 articleResult = ODBCCommand.ExecuteReader() ←ここで例外発生 ' 取得した件数分処理 While articleResult.Read() ' 子品番データを取得 sChild = articleResult("C_ARTICLE_NUMBER").ToString If sChild <> "" Then ' 子品番データをキーに図面マスタからデータを取得するSQLを作成 zumenSql = "SELECT * FROM ""ZUMEN_MST"" WHERE ""PLAN_NUMBER"" = '" + sChild + "'" Else sParents = articleResult("P_ARTICLE_NUMBER").ToString zumenSql = "SELECT * FROM ""ZUMEN_MST"" WHERE ""PLAN_NUMBER"" = '" + sParents + "'" End If Debug.WriteLine("【ArticleTableUpdate】 図面マスタからデータを取得SQL:" + zumenSql) ODBCCommand2.CommandText = zumenSql ' 図面マスタから該当の品番のデータの件数を取得 zumenCount = ODBCCommand2.ExecuteNonQuery ' 図面マスターに該当の品番のデータが存在するか If zumenCount = 0 Then ' 図面データが存在しない為、更新値を0とする zumenFlag = "0" Else ' 図目データが存在する為、更新値を1とする zumenFlag = "1" End If ' 品番テーブルを更新するSQLを作成 zumenSql = "UPDATE ""ARTICLE_TBL"" " + vbCrLf + "SET " + vbCrLf + vbTab + """C_ARTICLE_NUMBER"" = '" + sChild + "', " + vbCrLf + vbTab + """PLAN_FLAG"" = '" + zumenFlag + "', " + vbCrLf + vbTab + """UPDATE_DATE"" = '" + Today + "'" + vbCrLf + "WHERE ""P_ARTICLE_NUMBER"" = '" + sParents + "'" Debug.WriteLine("【ArticleTableUpdate】 品番テーブルを更新するSQL:" + zumenSql) ODBCCommand2.CommandText = zumenSql ' 品番テーブルを更新 zumenCount = ODBCCommand2.ExecuteNonQuery() End While articleResult.Close() ODBCCommand = New Odbc.OdbcCommand ODBCCommand.Connection = ODBCSession End Sub 【DB接続関数】 Public Function ODBC_CONNECT() As Boolean ' 戻り値をセット ODBC_CONNECT = False If ConnectFlag = False Then Try ODBCSession = New Odbc.OdbcConnection ODBCCommand = New Odbc.OdbcCommand ODBCCommand2 = New Odbc.OdbcCommand ' データベース接続情報 ODBCSession.ConnectionString = "Provider=MSDASQL;DSN=HOGE;UID=hogeU;PWD=hogeP;" ODBCCommand.Connection = ODBCSession ODBCCommand2.Connection = ODBCSession ' データベースに接続 ODBCSession.Open() ConnectFlag = True ODBC_CONNECT = True Catch Debug.WriteLine("えらー") End Try End If End Function 今のところ、このエラーが発生した場合、再起動すると発生しなくなるみたいです。(たまたまそうなったのかもしれません) 何か原因がわかる方、ご教授お願い致します。
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- MARU4812
- ベストアンサー率43% (196/452)
プログラムの造りが悪いです 行儀が悪いプログラムです。 ODBCSession ODBCCommand ODBCCommand2 をグローバルで定義して (使いまわして)いるので、自分が使ったら、次の処理のためにそれぞれの 後始末をしてやる必要があります。 ArticleTableUpdate 以外でも使っているのであれば、そっちに問題が あったときにどうしようもないです。 他人のふんどしを使っているというか、他人任せ、直前の処理に依存。 しかも依存する利点は無いという。。。 当の ArticleTableUpdate 内部の処理でもエラートラップされていないし、 処理が終わって New するくらいなら、自分が使う前にやればいいのに。 もしかしてこれを後始末だと思っているんでしょうか? 次の処理の準備までは出しゃばるけど、実際の処理までは面倒見れない とか、余計なお世話でしかありません。 関数を分ける実力が無さそうなので、1つの関数で ・データベースに接続(インスタンスの生成からローカルで行い、グローバル な変数を使わない) ・SQLで処理 ・データベースから切断(接続を閉じた後、使ったインスタンスも破棄) と行儀よくきちんと閉じるように、 最初から最後まで自分の関数内で面倒を見た方がいいのでは?
お礼
ありがとうございます。 確かに別の関数が原因でした。 元のプログラム(VB6)からのバージョンアップって事で、元のソースからこんなつくりでした(言い訳にしかならないですけど。) エラートラップのは、別クラス?のを使いまわししていてvisual stduio2010で元のソースをアップグレードしたらエラーになった為にはずしただけです。 これで完成というわけではありません。(これも言い訳ですが。) 私はどちらかというと、動けば良いという考えの人間なので、行儀の良いとかはよくわかりません。 ちゃんとお金が発生するなら上の人・先輩等に聞きますが、発生しているわけではないので別にいいかなーと。 後でレビューした時に一杯言われますしね。 MARU4812さんがおっしゃったような事は少なからず言われるでしょうから、レビュー前に直します。