- - PR -
ODPについて
1
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-06-28 17:20
はじめまして、asahiです。
いつも参考にさせていただいています。 ODPを使用して検索を行いたいのですが、以下の部分でエラーが出てしまいます。 検索を行うたびにDBへの接続を行わないようにするため、処理毎にメソッドを作ってみましたが、そもそもこのようなやり方は間違っているのでしょうか? 行っているのは以下のとおりです。 『Windowsアプリケーション』 Public Class Form Inherits System.Windows.Forms.Form Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim data As String Dim Database As String = "DBNAME" Dim UserID As String = "USERID" Dim Password As String = "PASS" Dim sSQL As String = "SELECT COLUMN FROM TABLE" 'DB接続 P_ODP.OpenDataBase(Database, UserID, Password) 'DB検索 data = P_ODP.OpenRecordset(sSQL) ←エラー me.textbox1.text = data 'DB切断 P_ODP.CloseDataBase() End Sub End Class エラー内容 *************************************** 'System.Web.Services.Protocols.SoapException'のハンドルされていない例外がsystem.web.services.dllで発生しました。 追加情報:System.Web.Services.Protocols.SoapException:サーバは要求を処理できませんでした。--->System.InvalidOperationException:オブジェクトの現在の状態に問題があるため、操作は有効ではありません。 *************************************** 『Webサービス』 Imports System.Web.Services Imports Oracle.DataAccess.Client Imports Oracle.DataAccess.Types <WebService(Namespace := "http://tempuri.org/")> _ Public Class ODPService Inherits System.Web.Services.WebService Private con As OracleConnection '接続 <WebMethod()> Public Sub OpenDataBase(ByVal DatabaseName As String, ByVal UserName As String, ByVal Password As String) As Boolean con = New OracleConnection() con.ConnectionString = "User Id=" & UserName & ";Password=" & Password & ";Data Source=" & DatabaseName & ";" con.Open() End Function '切断 <WebMethod()> Public Sub CloseDatabase() con.Close() con.Dispose() End Sub '検索 <WebMethod()> Public Function OpenRecordset(ByVal SQL As String) As String Dim data As String Dim cmd As OracleCommand = New OracleCommand(SQL) cmd.Connection = con cmd.CommandType = CommandType.Text Dim reader As OracleDataReader = cmd.ExecuteReader() reader.Read() data = reader.GetString(0) End Sub End Class 開発環境はWindoows2000、.NET2002(VisualBasic)、ORACLE9i、.NETFramework1.1です。 どうぞよろしくお願いします。 | ||||||||||||
|
投稿日時: 2004-06-28 17:40
あまりにも突っ込み所がありすぎて困るぐらいですが……ひとつだけ。
OpenDataBaseメソッドでODPServiceクラスのメンバにConnectionを保持したところで、次にOpenRecordSetメソッドを呼び出したときにそのConnectionが使えるということはありません。 ODPServiceクラスは、呼び出されるたびにインスタンスが生成され、破棄されると考えてください。 http://www.atmarkit.co.jp/fdotnet/entwebapp/entwebapp02/entwebapp02_02.html [ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-06-28 17:41 ] | ||||||||||||
|
投稿日時: 2004-06-28 21:27
では、それ以外の突っ込みどころをば。
1つ目。
DBMSへの接続と切断の間が長すぎます。だいいち接続したまま切断を忘れたりしたら……。 DB接続/切断は極力短くして、接続Poolに任せましょう。 2つ目。
危な〜〜〜〜〜〜〜〜〜〜い!! もしも "SQL" に "DELETE FROM TABLE; SELECT 'HOGEHOGE' AS COLUMN FROM DUAL" だの "DROP TABLE TABLE; SELECT 'HOGEHOGE' AS COLUMN FROM DUAL"(←あれ?) だの入れられたらど〜すんですか? 《SQL文をちょこっと修正←合ってたかな?》 [ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-06-29 08:08 ] | ||||||||||||
|
投稿日時: 2004-06-29 08:46
こうかな? SELECT PASSWORD FROM USERS WHERE NAME=''; SELECT TABLE_NAME FROM TABS; --'; 太字がユーザ入力。つまり、ユーザ名を入れてもらって、パスワードを取り出して照会しようとする。そこでSQL文は次のようになる。 SELECT PASSWORD FROM USERS WHERE NAME='ユーザ名'; ところが、悪意やいたずら心を持ったユーザが、次のように入力する。 '; SELECT TABLE_NAME FROM TABS; -- すると、作りによってはテーブル一覧が表示されてしまう。その後、もう一度入力するときに '; DROP TABLE テーブル名; -- と入力すると、テーブルが削除される。。。 | ||||||||||||
|
投稿日時: 2004-06-29 09:29
ぢゃん♪さん、Jittaさん、返答ありがとうございます。
大変勉強になりました。 SQL文を渡すことでいろいろなことができてしまうとは、気付いていませんでした。 早速考えなおしてみようと思います。 他に突っ込むところがあればよろしくお願いします。 すみません、初心者の私にもう少しだけお付き合い願いたいのですが。 確認として、SQLを実行する場合はその都度DBに接続し切断すると理解していいんですよね? 私が作成したWebサービスは機能毎にメソッドを分割しないで一つのメソッドにまとめるということで。 | ||||||||||||
|
投稿日時: 2004-06-29 11:34
メソッドを分割するのはあっています。「メソッドをまとめる」のではなく、「1メソッドの呼び出しで、1連の流れを実行する」ようにします。 具体的には、サービスは「**のデータを取り出す」メソッドだけを“公開”(public)し、その他に「データベースを開く」、「データベースを閉じる」という、“非公開”(private/protected)のメソッドを持ちます。 「**のデータを取り出す」メソッドがコールされると、その中で「データベースを開く」メソッドを呼び出し、処理を行い、「データベースを閉じる」メソッドを呼び出します。 | ||||||||||||
|
投稿日時: 2004-06-29 11:49
Jittaさん、ありがとうございます。
これで自分のなかにあったもやもやがやっと晴れました。 なるほど、そうやって作ればいいんですね。 早速作って見たいと思います。 また、お世話になると思いますがよろしくお願いします。 |
1