You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
11 KiB

VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "Account"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Attribute VB_Description = "APE MTS Transaction Service (Account)"
Option Explicit
Implements APEInterfaces.IMTSAccount
Private Const E_NOTIMPL = &H80004001
Private Const mlSTARTINGBALANCE = 1000000 ' Starting
Public Sub Post(sConnect As String, eConnectOptions As ape_DbConnectionOptions, lAccountNo As Long, lAmount As Long)
'-------------------------------------------------------------------------
'Purpose:
' Provides an interface for late binding. Late binding is only provided
' for test comparison. Other custom services should only use the implemented
' interface.
'-------------------------------------------------------------------------
IMTSAccount_Post sConnect, eConnectOptions, lAccountNo, lAmount
End Sub
Private Sub IMTSAccount_Post(sConnect As String, eConnectOptions As APEInterfaces.ape_DbConnectionOptions, lAccountNo As Long, lAmount As Long)
Dim lBalance As Long
Dim sSQLUpdate As String
Dim sSQLBalance As String
' Get our object context
Dim ctxObject As ObjectContext
Set ctxObject = GetObjectContext()
sSQLUpdate = "UPDATE Account SET Balance = Balance + " + Str$(lAmount) + " WHERE AccountNo = " + Str$(lAccountNo)
sSQLBalance = "SELECT Balance FROM Account WHERE AccountNo = " + Str$(lAccountNo)
On Error GoTo PostError
Select Case eConnectOptions
Case ape_DbConnectionOptions.ape_idcADO
If lAmount < 0 Then ' If debit, then get balance
PostADO sConnect, sSQLUpdate, sSQLBalance, lBalance
Else
PostADO sConnect, sSQLUpdate, sSQLBalance
End If
Case ape_DbConnectionOptions.ape_idcRDO
If lAmount < 0 Then ' If debit, then get balance
PostRDO sConnect, sSQLUpdate, sSQLBalance, lBalance
Else
PostRDO sConnect, sSQLUpdate, sSQLBalance
End If
Case ape_DbConnectionOptions.ape_idcDAO
If lAmount < 0 Then ' If debit, then get balance
PostDAO sConnect, sSQLUpdate, sSQLBalance, lBalance
Else
PostDAO sConnect, sSQLUpdate, sSQLBalance
End If
Case ape_DbConnectionOptions.ape_idcODBC
If lAmount < 0 Then ' If debit, then get balance
PostODBCAPI sConnect, sSQLUpdate, sSQLBalance, lBalance
Else
PostODBCAPI sConnect, sSQLUpdate, sSQLBalance
End If
Case Else
Err.Raise E_NOTIMPL
End Select
If lAmount < 0 And lBalance < 0 Then ' If a debit and acount is overdrawn
IMTSAccount_Post sConnect, eConnectOptions, lAccountNo, mlSTARTINGBALANCE ' Give a new starting balance
End If
ctxObject.SetComplete ' Transaction completed
Exit Sub
PostError:
Dim lErrorNumber As Long
Dim sErrorDescription As String
sErrorDescription = Err.Description
lErrorNumber = Err.Number
ctxObject.SetAbort ' Transaction aborted
' Need to explicitly set the error source to AEMTSSvc
Err.Raise lErrorNumber, "AEMTSSvc", LoadResString(ERROR_POSTING_TO_ACCOUNT) & " (" & sErrorDescription & ")"
End Sub
Private Sub PostADO(sConnect As String, sSQLUpdate As String, sSQLBalance As String, Optional lBalance As Long)
' If adoConnection throws an exception
On Error GoTo PostadoError
' Obtain the ADO connection
Dim adoConn As New ADODB.Connection
adoConn.Open sConnect
' Update the balance
adoConn.Execute sSQLUpdate
If Not IsMissing(lBalance) Then
' Get resulting balance which may have been further updated via triggers
Dim adoRS As ADODB.Recordset
Set adoRS = adoConn.Execute(sSQLBalance)
If Not adoRS.EOF Then
lBalance = adoRS.Fields("Balance").Value
Else
Err.Raise errInvalidAccount
End If
adoRS.Close
End If
adoConn.Close
Exit Sub
PostadoError:
Dim lErrorNumber As Long
Dim sErrorDescription As String
sErrorDescription = Err.Description
lErrorNumber = Err.Number
If Not adoRS Is Nothing Then
adoRS.Close
End If
If Not adoConn Is Nothing Then
adoConn.Close
End If
If lErrorNumber <> 0 Then
Err.Raise lErrorNumber, , sErrorDescription
End If
End Sub
Private Sub PostRDO(sConnect As String, sSQLUpdate As String, sSQLBalance As String, Optional lBalance As Long)
' If rdoConnection throws an exception
On Error GoTo PostRDOError
' Obtain the RDO environment and connection
Dim rdoConn As rdoConnection
Set rdoConn = rdoEngine.rdoEnvironments(0).OpenConnection("", rdDriverNoPrompt, False, sConnect)
' Update the balance
rdoConn.Execute sSQLUpdate
If Not IsMissing(lBalance) Then
' Get resulting balance which may have been further updated via triggers
Dim rdoRS As rdoResultset
Set rdoRS = rdoConn.OpenResultset(sSQLBalance)
If Not rdoRS.EOF Then
lBalance = rdoRS.rdoColumns("Balance")
Else
Err.Raise errInvalidAccount
End If
rdoRS.Close
End If
rdoConn.Close
Exit Sub
PostRDOError:
Dim lErrorNumber As Long
Dim sErrorDescription As String
sErrorDescription = Err.Description
lErrorNumber = Err.Number
If Not rdoRS Is Nothing Then
rdoRS.Close
End If
If Not rdoConn Is Nothing Then
rdoConn.Close
End If
If lErrorNumber <> 0 Then
Err.Raise lErrorNumber, , sErrorDescription
End If
End Sub
Private Sub PostDAO(sConnect As String, sSQLUpdate As String, sSQLBalance As String, Optional lBalance As Long)
' If daoConnection throws an exception
On Error GoTo PostDAOError
' Obtain the DAO workspace and connection
Dim daoWorkspace As Workspace
Dim daoConn As Connection
Set daoWorkspace = CreateWorkspace("", "", "", dbUseODBC)
Set daoConn = daoWorkspace.OpenConnection("", dbDriverNoPrompt, False, "ODBC;" & sConnect)
' Update the balance
daoConn.Execute sSQLUpdate
If Not IsMissing(lBalance) Then
' Get resulting balance which may have been further updated via triggers
Dim daoRS As Recordset
Set daoRS = daoConn.OpenRecordset(sSQLBalance)
If Not daoRS.EOF Then
lBalance = daoRS.Fields("Balance").Value
Else
Err.Raise errInvalidAccount
End If
daoRS.Close
End If
daoConn.Close
Exit Sub
PostDAOError:
Dim lErrorNumber As Long
Dim sErrorDescription As String
sErrorDescription = Err.Description
lErrorNumber = Err.Number
If Not daoRS Is Nothing Then
daoRS.Close
End If
If Not daoConn Is Nothing Then
daoConn.Close
End If
If lErrorNumber <> 0 Then
Err.Raise lErrorNumber, , sErrorDescription
End If
End Sub
Private Sub PostODBCAPI(sConnect As String, sSQLUpdate As String, sSQLBalance As String, Optional lBalance As Long)
' Handles for the ODBC API calls
Dim hEnvironment As Long
Dim hConnection As Long
Dim hStatement As Long
Dim iConnectLength As Integer
On Error GoTo PostODBCAPIError
If Not ODBCAPICallSuccessful(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, hEnvironment)) Then
Err.Raise ErrorAllocateHandle, , LoadResString(ErrorAllocateHandle)
End If
If Not ODBCAPICallSuccessful(SQLSetEnvAttrLong(hEnvironment, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, 0)) Then
Err.Raise ErrorSetAttribute, , LoadResString(ErrorSetAttribute)
End If
If Not ODBCAPICallSuccessful(SQLAllocHandle(SQL_HANDLE_DBC, hEnvironment, hConnection)) Then
Err.Raise ErrorAllocateHandle, , LoadResString(ErrorAllocateHandle)
End If
If Not ODBCAPICallSuccessful(SQLDriverConnect(hConnection, 0, sConnect, _
LenB(sConnect), vbNullString, 0, iConnectLength, SQL_DRIVER_NOPROMPT)) Then
Err.Raise ErrorConnectDriver, , LoadResString(ErrorConnectDriver)
End If
If Not ODBCAPICallSuccessful(SQLAllocHandle(SQL_HANDLE_STMT, hConnection, hStatement)) Then
Err.Raise ErrorAllocateHandle, , LoadResString(ErrorAllocateHandle)
End If
If Not ODBCAPICallSuccessful(SQLSetStmtAttrLong(hStatement, SQL_CURSOR_TYPE, SQL_CURSOR_STATIC, 0)) Then
Err.Raise ErrorSetAttribute, , LoadResString(ErrorSetAttribute)
End If
If Not ODBCAPICallSuccessful(SQLExecDirect(hStatement, sSQLUpdate, Len(sSQLUpdate))) Then
' See if the error is due to a resource deadlock
Dim iRecNum As Integer, iTextLen As Integer
Dim sSQLState As String * 5, sMsgText As String * 1
Dim lNativeErrorPtr As Long
iRecNum = 1
Do While ODBCAPICallSuccessful(SQLGetDiagRec(SQL_HANDLE_STMT, hStatement, iRecNum, sSQLState, lNativeErrorPtr, _
sMsgText, 0, iTextLen))
If sSQLState = "40001" Then
Err.Raise ErrorResourceDeadlock, , LoadResString(ErrorResourceDeadlock)
End If
iRecNum = iRecNum + 1
Loop
' Else, raise generic error
Err.Raise ErrorExecuteQuery, , LoadResString(ErrorExecuteQuery)
End If
If Not IsMissing(lBalance) Then
' Get resulting balance
If Not ODBCAPICallSuccessful(SQLExecDirect(hStatement, sSQLBalance, Len(sSQLBalance))) Then
Err.Raise ErrorExecuteQuery, , LoadResString(ErrorExecuteQuery)
End If
Select Case SQLFetchScroll(hStatement, SQL_FETCH_FIRST, 0)
Case SQL_NO_DATA
Err.Raise ErrorFetchRecord, , LoadResString(ErrorFetchRecord)
Case SQL_SUCCESS, SQL_SUCCESS_WITH_INFO
' Do nothing
Case Else
Err.Raise ErrorFetchRecord, , LoadResString(ErrorFetchRecord)
End Select
Dim lBalanceLength As Long
If Not ODBCAPICallSuccessful(SQLGetDataLong(hStatement, 1, SQL_INTEGER, lBalance, 0, lBalanceLength)) Then
Err.Raise ErrorGetData, , LoadResString(ErrorGetData)
End If
End If
PostODBCAPIError:
Dim lErrorNumber As Long
Dim sErrorDescription As String
sErrorDescription = Err.Description
lErrorNumber = Err.Number
SQLCloseCursor hStatement
SQLFreeHandle SQL_HANDLE_STMT, hStatement
SQLDisconnect hConnection
SQLFreeHandle SQL_HANDLE_DBC, hConnection
SQLFreeHandle SQL_HANDLE_ENV, hEnvironment
If lErrorNumber <> 0 Then
Err.Raise lErrorNumber, , sErrorDescription
End If
End Sub