- PR -

ASP.NETでDataReaderエラー

投稿者投稿内容
おひろ
ベテラン
会議室デビュー日: 2003/07/23
投稿数: 63
投稿日時: 2003-08-21 20:39
ASP.NETでSQLServer2000のテーブルを検索するプログラムを開発しています。
このプログラムをWEBサーバー経由で実行した際、1台のPCで使用している分には
問題なく動くのですが、複数の端末のブラウザから同時に動かすと
「この接続に関連付けられている DataReader が既に開いています。この DataReader を最初に閉じる必要があります。」
というエラーが頻発してしまいます。
DataReaderというのは、別PCからの接続だとしても1つしか開けないものなのでしょうか?
同じような経験のある方、情報をお持ちの方、ご教授いただけないでしょうか。
よろしくお願いいたします。
おひろ
ベテラン
会議室デビュー日: 2003/07/23
投稿数: 63
投稿日時: 2003-08-21 21:05
すいません、補足です。
人が作ったプログラムなのですが、エラーが出てるのはこのあたりかな。
いくつかのフォームに以下のような記述があります。
SqlDataAdapterを使用する=DataReaderを使用する、なのか・・・?

Dim dad As New SqlDataAdapter("SELECT * FROM M_FNCSECDTL", con)
Dim dst As New DataSet()
Dim strSQL As String 'SQL文格納用
Dim dv As New DataView()
Dim drv As DataRowView

strSQL = "SELECT * FROM F_BATLOG WHERE (EMPNO ='" & Session("user") & "') AND (ERRCHKFLG = 0)"
dad.SelectCommand.CommandText = strSQL
dst = New DataSet()
dad.Fill(dst)
dv = dst.Tables(0).DefaultView
小野@どっとねっとふぁん
ぬし
会議室デビュー日: 2001/10/30
投稿数: 402
投稿日時: 2003-08-21 23:04
提示されたコードはDataSetを利用しているので、ここが問題じゃありませんね。
DataReaderを利用しているところを探してください。

#VB.NETだし、Moduleのあたりがあやしい。

あと、Webアプリはサーバ上で動作しますので、クライアントが複数ある場合、
サーバ上の1つのシステムがDBに何回もつなぎにいく、というような
動作になります。

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-08-22 09:08
引用:

おひろさんの書き込み (2003-08-21 21:05) より:
Dim dad As New SqlDataAdapter("SELECT * FROM M_FNCSECDTL", con)


この、conは、なんですか?接続文字列 or SqlConnection?

 Webアプリと言うことなので、SqlConnectionが、1つ1つの端末からのアクセスごとに別のインスタンスになっていればいいのですが、Application変数やSession変数に格納するなどして「1つの接続で処理する」様にプログラムされているなら、これが原因です。アクセスごとに別のインスタンスになるように修正してください。

 これは「接続プールを利用する」とは別の問題です。「接続プール」を共有するのではなく、「接続」そのものを共有すると、問題が発生します。
おひろ
ベテラン
会議室デビュー日: 2003/07/23
投稿数: 63
投稿日時: 2003-08-22 12:44
小野@EACさん、Jittaさん、ありがとうございます。

conはSqlConnectionです。
 Public con As New SqlClient.SqlConnection("data source=xxx;initial  catalog=TESTDB;persist security info=False;user id=sa;workstation id=xxx;packet size=4096")

>Webアプリと言うことなので、SqlConnectionが、1つ1つの端末からのアクセスごとに別のインスタンスになっていればいいのですが、

SQLConnection conは各関数でSELECT文を発行するたびに以下のように定義されています。
これではまずいのでしょうか?
Dim dad As New SqlDataAdapter("SQL文", con)

>DataReaderを利用しているところを探してください。

それらしい部分がありましたので、ちょっと長いですがのせてみます。
con.open、con.closeとありますが、ここがまずいのでしょうか?

txtCOMKNRNO.Text = Session("t1")
txtKYKNO.Text = Session("t2")
txtTELNO.Text = Session("t3")
txtZIPNO.Text = Session("t4")
txtADRCD1.Text = Session("t5")
txtADRCD2.Text = Session("t6")
txtADRCD3.Text = Session("t7")
txtADRCD4.Text = Session("t8")
txtKYKNM.Text = Session("t9")
txtKYKNMKS.Text = Session("t10")
txtKYKNMKM.Text = Session("t11")
txtEMAIL.Text = Session("t12")
txtWEBKYKNO.Text = Session("t13")

Dim cmd As SqlCommand
If con.State = ConnectionState.Closed Then
con.Open()
End If
'[DropDownListコントロール(事業名)の追加]
cmd = New SqlCommand("SELECT M_CDMEI.KEYN, M_CDMEI.CDNM1 FROM M_JIGYOCTL INNER JOIN " & _
"M_CDMEI ON M_JIGYOCTL.JIGYOCD = M_CDMEI.KEYN INNER JOIN " & _
"M_JGYSECDTL ON M_JIGYOCTL.JIGYOCD = M_JGYSECDTL.JIGYOCD " & _
"WHERE (M_CDMEI.JIGYOCD = " & conGlb_JigyoCd_DAR & ") AND (M_CDMEI.CDKB = 928) AND " & _
"(M_CDMEI.DELFLG = 0) AND (M_CDMEI.KEYA = '') AND (M_JGYSECDTL.USEFLG = 1) AND (M_JGYSECDTL.JIGYOSECCD = '" & _
Session("jigyoseccd") & "')", con)
Dim drr As SqlDataReader = cmd.ExecuteReader()

' データ連結を設定します。
ddlJigyo.DataSource = drr
ddlJigyo.DataTextField = "CDNM1"
ddlJigyo.DataValueField = "KEYN"
ddlJigyo.DataBind()
ddlJigyo.SelectedItem.Value = Session("sv1")
ddlJigyo.SelectedItem.Text = Session("st1")
drr.Close()

' 接続を閉じます。
If con.State = ConnectionState.Open Then
con.Close()
End If

お手間をおかけして申し訳ありません。
よろしくお願いいたします。


きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2003-08-22 13:40
おひろさん、こんにちは。
引用:

 Public con As New SqlClient.SqlConnection("data source=xxx;initial  catalog=TESTDB;persist security info=False;user id=sa;workstation id=xxx;packet size=4096")


これ、conはモジュールレベル(メンバ)変数ですかね?
Jittaさんのいう、「アクセスごとに別のインスタンスになるように」するということは、DataAdapterのインスタンスと対になるように宣言・生成する、ということです。(よね?>Jittaさん)
DataAdapterはSQL発行の度に宣言してNewしているとの事ですが、その引数に指定されているcon自体は、全てのメソッドから同一のインスタンスが参照されているんじゃないですか?
取り敢えず、現在のPublicなconの宣言をコメントアウトして、コンパイルエラーとなる全ての
Dim dad As New SqlDataAdapter("SQL文", con)
という行の前に、ローカルなconの宣言と生成を書いてみて下さい。

おひろ
ベテラン
会議室デビュー日: 2003/07/23
投稿数: 63
投稿日時: 2003-08-22 20:17
きくちゃんさん、ありがとうございます。

あの後、まずはDataReaderを使用しているロジックをすべてDataAdapterを使用するように変更してみたのですが、同じエラーが出てしまいました。
きくちゃんさんのアドバイス通りやってみようかと思いますが、ちょっと疑問が。
エラーメッセージでは「DataReader」とあるのですが、現在このプログラムではDataReaderを明示的に使っている記述はないのです。
DataAdapterを使用した場合もDataReaderのエラーが出る可能性はあるのでしょうか。
あと、SQLServerやWEBサーバーの環境で発生する可能性はないでしょうか。

----エラーメッセージの一部を抜粋してみました-----

[InvalidOperationException: この接続に関連付けられている DataReader が既に開いています。この DataReader を最初に閉じる必要があります。]
System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean executing) +292
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream) +103
System.Data.SqlClient.SqlCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) +9
System.Data.Common.DbDataAdapter.Fill(Object data, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) +121
System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) +77
System.Data.Common.DbDataAdapter.Fill(DataSet dataSet) +38
uel.detail1.GetComkyk(DataRowView drv) in C:\vsnet\uel\detail1.aspx.vb:126
ASP.detail1_aspx.__DataBind__control7(Object sender, EventArgs e) in E:\uel\detail1.aspx:51
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-08-25 08:20
引用:

おひろさんの書き込み (2003-08-22 20:17) より:

あの後、まずはDataReaderを使用しているロジックをすべてDataAdapterを使用するように変更してみたのですが、同じエラーが出てしまいました。


 何か勘違いされていませんか?DataReaderをDataAdapterに置き換えるのではなく、Connectionのインスタンスを独立させるのです。DataReaderを使っていても、Connectionのインスタンスが独立していれば問題ありません。

 ここの過去ログの中にあるのですが、ASP.NETをVB.NETで実装する際、MODULEを使うと、特殊な働きをするそうです。まずはMODULEを全廃する方向で考える方がいいかと思います。

引用:

きくちゃんさんの書き込み(2003-08-22 13:40):

DataAdapterのインスタンスと対になるように宣言・生成する
現在のPublicなconの宣言をコメントアウトして、コンパイルエラーとなる全ての
Dim dad As New SqlDataAdapter("SQL文", con)
という行の前に、ローカルなconの宣言と生成を書いてみて下さい。



具体例:
Module
Public con As New SqlClient.SqlConnection…

End Module
を削除する。

Dim dad As New SqlDataAdapter("SELECT * FROM M_FNCSECDTL", con)
を、
Dim dad As New SqlDataAdapter("SELECT * FROM M_FNCSECDTL", "data source=xxx;…")
に修正する。
〜〜〜〜〜
具体例2:
Public con As New SqlClient.SqlConnection…
を、
Public con As String = "data source=xxx;…"
に修正する。

−−−−−
追加:
 DataAdapter内部でDataReaderが使われているので、「DataRederで…」というメッセージになります。引用されているのは呼出履歴です。下から上にメソッドが呼ばれています。

[ メッセージ編集済み 編集者: Jitta 編集日時 2003-08-25 08:24 ]

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