たにぐちBLOG

C#が好きでたまんない

  PASSJブログ :: ホーム :: 連絡をする :: RSS  :: ATOM :: Login
  31 投稿数 :: 0 ストーリー :: 56 コメント :: 10 トラックバック

過去の記事

カテゴリ

イメージギャラリ

2005年7月9日 #

http://blogs.sqlpassj.org/masatotaniguchi/archive/2005/06/10/9475.aspx
のASP版(非ASP.NET)です。ActiveX dllを使用し、ASPファイルからデータアクセス部分を分離、少ない変更で複数のデータベースに対応できるようにします。

Visual Basic 6.0で、ActiveX dllを作成し、ScottDAOという名前をつけます。これは、以前にご紹介したVB6版をActiveX dll化したものです。
※以下のソースコードはエラー処理などが省略してあり、完全ではありません。

テーブル(OracleのScott.Empテーブルと、それをSQL Server 2000にインポートしたテーブル)のレコードを保存するために、VO(Value Object)を用意します。これはVB6版と全く同じでそのまま移植できます。
Instancingプロパティは5-MultiUseとします


' ソースコード(clsEmpVo):クラスモジュール

' Private 変数
' 従業員番号
Private m_lngEmpNo As Long
' 従業員名
Private m_strEname As String

' 以下略

' プロパティ

Public Property Get EMPNO() As Long
    EMPNO = m_lngEmpNo
End Property

Public Property Let EMPNO(lngEmpNo As Long)
    m_lngEmpNo = lngEmpNo
End Property

Public Property Get Ename() As String
    Ename = m_strEname
End Property

Public Property Let Ename(strEname As String)
    m_strEname = strEname
End Property

' 以下略(フィールド分同じものを作ります)


インターフェースクラスは外部に公開したいため、Instancingプロパティを5-MultiUseとします。
これをこのまま公開しても、中は空っぽです。後でちょっと細工をします。




' ソースコード(clsEmpDao) :クラスモジュール

Public Function SelectEmp(lngDeptNo As Long) As Collection

End Function

Public Function InsertEmp(EmpVo As clsEmpVo) As Boolean

End Function

Public Function UpdateEmp(EmpVo As clsEmpVo) As Boolean

End Function

Public Property Set Connection(con As Object)
   
End Property


clsEmpSQLServerDaoはVB6版とほとんど同じです(選択条件が部署番号になっている部分だけが違います)。このクラスは外部に公開しないため、Instancingプロパティを1-Privateとします。
Oracleについても全く同じなので、ここでは省略します。VB6版をご参照ください。
なお、nvl関数は標準モジュールにある独自の関数で動作はORACLEのNVLと全く同じです。


' ソースコード(clsEmpSQLServerDao):クラスモジュール

Implements clsEmpDao

Private Connection As Object

Public Property Set clsEmpDao_Connection(con As Object)
    Set Connection = con
End Property

Public Function clsEmpDao_SelectEmp(lngDeptNo As Long) As Collection

    Dim cmd As New ADODB.Command
    Dim result As New Collection
    Dim rs As ADODB.Recordset
   
    ' Commandの設定
    With cmd
        .ActiveConnection = Connection
        .CommandText = "SELECT * FROM EMP WHERE DEPTNO = ?"
        .CreateParameter , adInteger, adParamInput
        .Parameters(0).Value = lngDeptNo
    End With
   
    ' SQLを実行して結果セットを取得します
    Set rs = cmd.Execute

    ' Recordsetから、VOへ値を詰めます
    Do Until rs.EOF
        Dim EmpVo As clsEmpVo
        Set EmpVo = New clsEmpVo
        EmpVo.EmpNo = nvl(rs.Fields("EMPNO"), 0)
        EmpVo.Ename = nvl(rs.Fields("ENAME"), "")
        EmpVo.Job = nvl(rs.Fields("JOB"), "")
        EmpVo.Mgr = nvl(rs.Fields("MGR"), 0)
        EmpVo.HireDate = nvl(rs.Fields("HireDate"), 0)
        EmpVo.Sal = nvl(rs.Fields("SAL"), 0)
        EmpVo.Comm = nvl(rs.Fields("COMM"), 0)
        EmpVo.DeptNo = nvl(rs.Fields("DEPTNO"), 0)
        Call result.Add(EmpVo)
        rs.MoveNext
    Loop
   
    ' 後始末
    rs.Close
    Set rs = Nothing
    ' 戻り値(VOのコレクション)の設定
    Set clsEmpDao_SelectEmp = result
End Function

Public Function clsEmpDao_InsertEmp(EmpVo As clsEmpVo) As Boolean
    ' 省略
End Function

Public Function clsEmpDao_UpdateEmp(EmpVo As clsEmpVo) As Boolean
    ' 省略
End Function


さて、公開したいのはEmpDaoですがASPに渡したいのは中身の詰まったクラスです。
そこで以下のようなクラスを作成し外部に公開します(Instancingプロパティを5-MultiUse)。
データベースを変更する必要が出た時はここを変更します。


' ソースコード(clsScottDaoFactory):クラスモジュール

' このクラスが生成するDAOは、clsScottDaoFactory
' のインスタンスが存命中の場合のみ使用できます。
' clsScottDaoFactoryインスタンスの消滅とともにDB
'
接続も自動的にCloseされるためです。

Private Connection As clsConnection

Public Function EmpDAO() As clsEmpDao
   Dim emp As clsEmpDao
   ' DB変更時、コードの変更が必要な場所
   Set emp = New clsEmpSQLServerDao
   ' Set emp = New clsEmpOracleDao
   Set Emp.Connection = Connection.GetConnection   
   Set EmpDAO = emp
End Function

Private Sub Class_Initialize()
   Dim ConnectionFactory As New clsConnectionFactory
   Set Connection = ConnectionFactory.GetClsConnection
End Sub

' このメソッドは使用後、なるべく早く実行するようにします。
Public Sub CloseConnection()
    Connection.CloseConnection
    Set Connection = Nothing
End Sub

' 安全策
Private Sub Class_Terminate()
    If Not Connection Is Nothing Then
        Connection.CloseConnection
    End If
End Sub


DBの接続のためのクラス、clsConnectionを定義します。これはインターフェースとして扱います(Instancingプロパティを5-MultiUse)。


' ソースコード(clsConnection):クラスモジュール

Public Function GetConnection() As Object
   
End Function

Public Sub CloseConnection()
   
End Sub


SQLServerのためのclsConnectionの実装クラスを定義します(Instancingプロパティを1-Private)。Oracle用のclsOracleConnectionは省略します。


' ソースコード(clsSQLServerConnection):クラスモジュール

Implements clsConnection

Private adoSQLServerCon As ADODB.Connection

Public Function clsConnection_GetConnection() As Object
    Set clsConnection_GetConnection = adoSQLServerCon
End Function

Public Sub clsConnection_CloseConnection()
    adoSQLServerCon.Close
    Set adoSQLServerCon = Nothing
End Sub

Private Sub Class_Initialize()
   Set adoSQLServerCon = New ADODB.Connection
    adoSQLServerCon.ConnectionString = _
        "PROVIDER=SQLOLEDB;SERVER=ServerName;DATABASE=Scott;UID=sa;PWD=*******"
    adoSQLServerCon.Open
End Sub


clsConnectionクラスを作成するためのクラスを定義します(Instancingプロパティを5-MultiUse)。

' ソースコード(clsConnectionFactory):クラスモジュール

Public Function GetClsConnection() As clsConnection
   ' DB変更時、コードの変更が必要な場所
  
Set GetClsConnection = New clsSQLServerConnection
   ' Set GetClsConnection = New clsOracleConnection
End Function


以上のActiveX dllを作成しレジストリに登録します。これをテストするためのASPファイルを用意しました。
For Eachが不安な方は、レコード数をresult.countで取得できるのでFor...Next文で書き換えてもいいと思います。


' ソースコード(ScottEmp.asp):aspファイル

<HTML>
<BODY>
<%
Set scottDAOFactory = Server.CreateObject("ScottDAO.clsScottDAOFactory")
Set empDAO = scottDAOFactory.EmpDAO
Set result = empDAO.SelectEmp(20)
scottDAOFactory.CloseConnection
%>
<TABLE border="1">
<TR>
   <TH>従業員番号</TH>
   <TH>名前</TH>
   <TH>職種</TH>
   <TH>上司</TH>
   <TH>入社日</TH>
   <TH>給料</TH>
   <TH>歩合</TH>
   <TH>部署番号</TH>
</TR>
<%
For Each empVo In result
%>
<TR>
   <TD><%=empVo.EmpNo%></TD>
   <TD><%=empVo.Ename%></TD>
   <TD><%=empVo.Job%></TD>
   <TD><%=EmpVo.Mgr%></TD>
   <TD><%=EmpVo.Hiredate%></TD>
   <TD><%=empVo.Sal%></TD>
   <TD><%=EmpVo.Comm%></TD>
   <TD><%=empVo.deptNo%></TD>
</TR>
<%
Next
%>
</TABLE>
</BODY>
</HTML>


基本方針は、

aspファイルには画面表示ロジック以外はなるべく書かないようにする

ということです。ビジネスロジックもActiveX dllでカプセル化し、aspファイルからはそれを呼ぶだけにするようにします。

posted @ 2:43 | Feedback (12)