- - PR -
ASP.NETでDataReaderエラー
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-08-21 20:39
ASP.NETでSQLServer2000のテーブルを検索するプログラムを開発しています。
このプログラムをWEBサーバー経由で実行した際、1台のPCで使用している分には 問題なく動くのですが、複数の端末のブラウザから同時に動かすと 「この接続に関連付けられている DataReader が既に開いています。この DataReader を最初に閉じる必要があります。」 というエラーが頻発してしまいます。 DataReaderというのは、別PCからの接続だとしても1つしか開けないものなのでしょうか? 同じような経験のある方、情報をお持ちの方、ご教授いただけないでしょうか。 よろしくお願いいたします。 | ||||||||
|
投稿日時: 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 | ||||||||
|
投稿日時: 2003-08-21 23:04
提示されたコードはDataSetを利用しているので、ここが問題じゃありませんね。
DataReaderを利用しているところを探してください。 #VB.NETだし、Moduleのあたりがあやしい。 あと、Webアプリはサーバ上で動作しますので、クライアントが複数ある場合、 サーバ上の1つのシステムがDBに何回もつなぎにいく、というような 動作になります。 | ||||||||
|
投稿日時: 2003-08-22 09:08
この、conは、なんですか?接続文字列 or SqlConnection? Webアプリと言うことなので、SqlConnectionが、1つ1つの端末からのアクセスごとに別のインスタンスになっていればいいのですが、Application変数やSession変数に格納するなどして「1つの接続で処理する」様にプログラムされているなら、これが原因です。アクセスごとに別のインスタンスになるように修正してください。 これは「接続プールを利用する」とは別の問題です。「接続プール」を共有するのではなく、「接続」そのものを共有すると、問題が発生します。 | ||||||||
|
投稿日時: 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-22 13:40
おひろさん、こんにちは。
これ、conはモジュールレベル(メンバ)変数ですかね? Jittaさんのいう、「アクセスごとに別のインスタンスになるように」するということは、DataAdapterのインスタンスと対になるように宣言・生成する、ということです。(よね?>Jittaさん) DataAdapterはSQL発行の度に宣言してNewしているとの事ですが、その引数に指定されているcon自体は、全てのメソッドから同一のインスタンスが参照されているんじゃないですか? 取り敢えず、現在のPublicなconの宣言をコメントアウトして、コンパイルエラーとなる全ての Dim dad As New SqlDataAdapter("SQL文", con) という行の前に、ローカルなconの宣言と生成を書いてみて下さい。 | ||||||||
|
投稿日時: 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 | ||||||||
|
投稿日時: 2003-08-25 08:20
何か勘違いされていませんか?DataReaderをDataAdapterに置き換えるのではなく、Connectionのインスタンスを独立させるのです。DataReaderを使っていても、Connectionのインスタンスが独立していれば問題ありません。 ここの過去ログの中にあるのですが、ASP.NETをVB.NETで実装する際、MODULEを使うと、特殊な働きをするそうです。まずはMODULEを全廃する方向で考える方がいいかと思います。
具体例: 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 ] |