- PR -

ODPについて

1
投稿者投稿内容
asahi
会議室デビュー日: 2004/06/28
投稿数: 17
投稿日時: 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です。

どうぞよろしくお願いします。
ぢゃん♪
大ベテラン
会議室デビュー日: 2003/06/12
投稿数: 208
お住まい・勤務地: 都内
投稿日時: 2004-06-28 17:40
あまりにも突っ込み所がありすぎて困るぐらいですが……ひとつだけ。
コード:
<WebService(Namespace := "http://tempuri.org/")> _

Public Class ODPService
Inherits System.Web.Services.WebService


OpenDataBaseメソッドでODPServiceクラスのメンバにConnectionを保持したところで、次にOpenRecordSetメソッドを呼び出したときにそのConnectionが使えるということはありません。
ODPServiceクラスは、呼び出されるたびにインスタンスが生成され、破棄されると考えてください。
http://www.atmarkit.co.jp/fdotnet/entwebapp/entwebapp02/entwebapp02_02.html

[ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-06-28 17:41 ]
ぢゃん♪
大ベテラン
会議室デビュー日: 2003/06/12
投稿数: 208
お住まい・勤務地: 都内
投稿日時: 2004-06-28 21:27
では、それ以外の突っ込みどころをば。
1つ目。
コード:

<WebMethod()> Public Sub OpenDataBase(ByVal DatabaseName As String, ByVal UserName As String, ByVal Password As String) As Boolean


コード:

<WebMethod()> Public Sub CloseDatabase()


DBMSへの接続と切断の間が長すぎます。だいいち接続したまま切断を忘れたりしたら……。
DB接続/切断は極力短くして、接続Poolに任せましょう。

2つ目。
コード:

<WebMethod()> Public Function OpenRecordset(ByVal SQL As String) As String
    Dim data As String
Dim cmd As OracleCommand = New OracleCommand(SQL)


危な〜〜〜〜〜〜〜〜〜〜い!!
もしも "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 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-06-29 08:46
引用:

ぢゃん♪さんの書き込み (2004-06-28 21:27) より:

《SQL文をちょこっと修正←合ってたかな?》


こうかな?

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 テーブル名; --
と入力すると、テーブルが削除される。。。
asahi
会議室デビュー日: 2004/06/28
投稿数: 17
投稿日時: 2004-06-29 09:29
ぢゃん♪さん、Jittaさん、返答ありがとうございます。
大変勉強になりました。
SQL文を渡すことでいろいろなことができてしまうとは、気付いていませんでした。
早速考えなおしてみようと思います。
他に突っ込むところがあればよろしくお願いします。

すみません、初心者の私にもう少しだけお付き合い願いたいのですが。

確認として、SQLを実行する場合はその都度DBに接続し切断すると理解していいんですよね?
私が作成したWebサービスは機能毎にメソッドを分割しないで一つのメソッドにまとめるということで。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-06-29 11:34
引用:

asahiさんの書き込み (2004-06-29 09:29) より:

SQLを実行する場合はその都度DBに接続し切断すると理解していいんですよね?
私が作成したWebサービスは機能毎にメソッドを分割しないで一つのメソッドにまとめるということで。


 メソッドを分割するのはあっています。「メソッドをまとめる」のではなく、「1メソッドの呼び出しで、1連の流れを実行する」ようにします。

 具体的には、サービスは「**のデータを取り出す」メソッドだけを“公開”(public)し、その他に「データベースを開く」、「データベースを閉じる」という、“非公開”(private/protected)のメソッドを持ちます。
 「**のデータを取り出す」メソッドがコールされると、その中で「データベースを開く」メソッドを呼び出し、処理を行い、「データベースを閉じる」メソッドを呼び出します。
asahi
会議室デビュー日: 2004/06/28
投稿数: 17
投稿日時: 2004-06-29 11:49
Jittaさん、ありがとうございます。
これで自分のなかにあったもやもやがやっと晴れました。
なるほど、そうやって作ればいいんですね。
早速作って見たいと思います。

また、お世話になると思いますがよろしくお願いします。
1

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