Imports System
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Data.ProviderBase
Imports System.Diagnostics
Imports System.EnterpriseServices
Imports System.Globalization
Imports System.Runtime.ConstrainedExecution
Imports System.Security
Imports System.Security.Permissions
Imports System.Threading
Imports System.Transactions
Namespace System.Data.OracleClient
<DefaultEvent("InfoMessage")> _
Public NotInheritable Class OracleConnection
Inherits DbConnection
Implements ICloneable
' Events
<ResCategory("OracleCategory_InfoMessage"), ResDescription("OracleConnection_InfoMessage")> _
Public Event InfoMessage As OracleInfoMessageEventHandler
AddHandler(ByVal value As OracleInfoMessageEventHandler)
MyBase.Events.AddHandler(OracleConnection.EventInfoMessage, value)
End AddHandler
RemoveHandler(ByVal value As OracleInfoMessageEventHandler)
MyBase.Events.RemoveHandler(OracleConnection.EventInfoMessage, value)
End RemoveHandler
End Event
' Methods
Public Sub New()
Me.ObjectID = Interlocked.Increment((OracleConnection._objectTypeCount))
GC.SuppressFinalize(Me)
Me._innerConnection = DbConnectionClosedNeverOpened.SingletonInstance
End Sub
Friend Sub New(ByVal connection As OracleConnection)
Me.New()
Me.CopyFrom(connection)
End Sub
Public Sub New(ByVal connectionString As String)
Me.New()
Me.ConnectionString = connectionString
End Sub
<ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)> _
Friend Sub Abort(ByVal e As Exception)
Dim comparand As DbConnectionInternal = Me._innerConnection
If (ConnectionState.Open = comparand.State) Then
Interlocked.CompareExchange(Of DbConnectionInternal)((Me._innerConnection), DbConnectionClosedPreviouslyOpened.SingletonInstance, comparand)
comparand.DoomThisConnection
End If
If TypeOf e Is OutOfMemoryException Then
Bid.Trace("<prov.DbConnectionHelper.Abort|RES|INFO|CPOOL> %d#, Aborting operation due to asynchronous exception: %ls" & ChrW(10), Me.ObjectID, "OutOfMemory")
Else
Bid.Trace("<prov.DbConnectionHelper.Abort|RES|INFO|CPOOL> %d#, Aborting operation due to asynchronous exception: %ls" & ChrW(10), Me.ObjectID, e.ToString)
End If
End Sub
Friend Sub AddWeakReference(ByVal value As Object, ByVal tag As Integer)
Me.InnerConnection.AddWeakReference(value, tag)
End Sub
Protected Overrides Function BeginDbTransaction(ByVal isolationLevel As IsolationLevel) As DbTransaction
Dim transaction As DbTransaction
Dim ptr As IntPtr
Bid.ScopeEnter(ptr, "<prov.DbConnectionHelper.BeginDbTransaction|API> %d#, isolationLevel=%d{ds.IsolationLevel}", Me.ObjectID, CInt(isolationLevel))
Try
transaction = Me.InnerConnection.BeginTransaction(isolationLevel)
Finally
Bid.ScopeLeave((ptr))
End Try
Return transaction
End Function
Public Function BeginTransaction() As OracleTransaction
Return Me.BeginTransaction(IsolationLevel.Unspecified)
End Function
Public Function BeginTransaction(ByVal il As IsolationLevel) As OracleTransaction
Return DirectCast(MyBase.BeginTransaction(il), OracleTransaction)
End Function
Public Overrides Sub ChangeDatabase(ByVal value As String)
Dim ptr As IntPtr
Bid.ScopeEnter(ptr, "<ora.OracleConnection.ChangeDatabase|API> %d#, value='%ls'" & ChrW(10), Me.ObjectID, value)
Try
Throw ADP.ChangeDatabaseNotSupported
Finally
Bid.ScopeLeave((ptr))
End Try
End Sub
Friend Sub CheckError(ByVal errorHandle As OciErrorHandle, ByVal rc As Integer)
Select Case DirectCast(rc, RETURNCODE)
Case RETURNCODE.OCI_INVALID_HANDLE
Throw ADP.InvalidOperation(Res.GetString("ADP_InternalError", New Object() { rc }))
Case RETURNCODE.OCI_ERROR, RETURNCODE.OCI_NO_DATA
Dim exception2 As Exception = ADP.OracleError(errorHandle, rc)
If ((Not errorHandle Is Nothing) AndAlso errorHandle.ConnectionIsBroken) Then
Dim openInternalConnection As OracleInternalConnection = Me.GetOpenInternalConnection
If (Not openInternalConnection Is Nothing) Then
openInternalConnection.ConnectionIsBroken
End If
End If
Throw exception2
Case RETURNCODE.OCI_SUCCESS_WITH_INFO
Dim infoMessageEvent As New OracleInfoMessageEventArgs(OracleException.CreateException(errorHandle, rc))
Me.OnInfoMessage(infoMessageEvent)
Return
End Select
If ((rc < 0) OrElse (rc = &H63)) Then
Throw ADP.Simple(Res.GetString("ADP_UnexpectedReturnCode", New Object() { rc.ToString(CultureInfo.CurrentCulture) }))
End If
End Sub
Public Shared Sub ClearAllPools()
New OraclePermission(PermissionState.Unrestricted).Demand
OracleConnectionFactory.SingletonInstance.ClearAllPools
End Sub
Public Shared Sub ClearPool(ByVal connection As OracleConnection)
ADP.CheckArgumentNull(connection, "connection")
Dim userConnectionOptions As DbConnectionOptions = connection.UserConnectionOptions
If (Not userConnectionOptions Is Nothing) Then
userConnectionOptions.DemandPermission
OracleConnectionFactory.SingletonInstance.ClearPool(connection)
End If
End Sub
Public Overrides Sub Close()
Me.InnerConnection.CloseConnection(Me, Me.ConnectionFactory)
End Sub
Friend Sub Commit()
Me.GetOpenInternalConnection.Commit
End Sub
Private Function ConnectionString_Get() As String
Bid.Trace("<prov.DbConnectionHelper.ConnectionString_Get|API> %d#" & ChrW(10), Me.ObjectID)
Dim shouldHidePassword As Boolean = Me.InnerConnection.ShouldHidePassword
Dim userConnectionOptions As DbConnectionOptions = Me.UserConnectionOptions
If (userConnectionOptions Is Nothing) Then
Return ""
End If
Return userConnectionOptions.UsersConnectionString(shouldHidePassword)
End Function
Private Sub ConnectionString_Set(ByVal value As String)
Dim userConnectionOptions As DbConnectionOptions = Nothing
Dim group As DbConnectionPoolGroup = Me.ConnectionFactory.GetConnectionPoolGroup(value, Nothing, (userConnectionOptions))
Dim innerConnection As DbConnectionInternal = Me.InnerConnection
Dim allowSetConnectionString As Boolean = innerConnection.AllowSetConnectionString
If allowSetConnectionString Then
allowSetConnectionString = Me.SetInnerConnectionFrom(DbConnectionClosedBusy.SingletonInstance, innerConnection)
If allowSetConnectionString Then
Me._userConnectionOptions = userConnectionOptions
Me._poolGroup = group
Me._innerConnection = DbConnectionClosedNeverOpened.SingletonInstance
End If
End If
If Not allowSetConnectionString Then
Throw ADP.OpenConnectionPropertySet("ConnectionString", innerConnection.State)
End If
If Bid.TraceOn Then
Dim str As String = IIf((Not userConnectionOptions Is Nothing), userConnectionOptions.UsersConnectionStringForTrace, "")
Bid.Trace("<prov.DbConnectionHelper.ConnectionString_Set|API> %d#, '%ls'" & ChrW(10), Me.ObjectID, str)
End If
End Sub
Private Sub CopyFrom(ByVal connection As OracleConnection)
ADP.CheckArgumentNull(connection, "connection")
Me._userConnectionOptions = connection.UserConnectionOptions
Me._poolGroup = connection.PoolGroup
Me._innerConnection = DbConnectionClosedNeverOpened.SingletonInstance
End Sub
Public Function CreateCommand() As OracleCommand
Dim command As New OracleCommand
command.Connection = Me
Return command
End Function
Protected Overrides Function CreateDbCommand() As DbCommand
Dim command As DbCommand = Nothing
Dim ptr As IntPtr
Bid.ScopeEnter(ptr, "<prov.DbConnectionHelper.CreateDbCommand|API> %d#" & ChrW(10), Me.ObjectID)
Try
command = Me.ConnectionFactory.ProviderFactory.CreateCommand
command.Connection = Me
Finally
Bid.ScopeLeave((ptr))
End Try
Return command
End Function
Private Shared Function CreateExecutePermission() As CodeAccessPermission
Dim permission As New OraclePermission(PermissionState.None)
permission.Add(String.Empty, String.Empty, KeyRestrictionBehavior.AllowOnly)
Return permission
End Function
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
Me._userConnectionOptions = Nothing
Me._poolGroup = Nothing
Me.Close
End If
Me.DisposeMe(disposing)
MyBase.Dispose(disposing)
End Sub
Private Sub DisposeMe(ByVal disposing As Boolean)
End Sub
Public Sub EnlistDistributedTransaction(ByVal distributedTransaction As ITransaction)
Me.EnlistDistributedTransactionHelper(distributedTransaction)
End Sub
Private Sub EnlistDistributedTransactionHelper(ByVal transaction As ITransaction)
Dim set As New PermissionSet(PermissionState.None)
[set].AddPermission(OracleConnection.ExecutePermission)
[set].AddPermission(New SecurityPermission(SecurityPermissionFlag.UnmanagedCode))
[set].Demand
Bid.Trace("<prov.DbConnectionHelper.EnlistDistributedTransactionHelper|RES|TRAN> %d#, Connection enlisting in a transaction." & ChrW(10), Me.ObjectID)
Dim transactionFromDtcTransaction As Transaction = Nothing
If (Not transaction Is Nothing) Then
transactionFromDtcTransaction = TransactionInterop.GetTransactionFromDtcTransaction(DirectCast(transaction, IDtcTransaction))
End If
Me.InnerConnection.EnlistTransaction(transactionFromDtcTransaction)
GC.KeepAlive(Me)
End Sub
Public Overrides Sub EnlistTransaction(ByVal transaction As Transaction)
OracleConnection.ExecutePermission.Demand
Bid.Trace("<prov.DbConnectionHelper.EnlistTransaction|RES|TRAN> %d#, Connection enlisting in a transaction." & ChrW(10), Me.ObjectID)
Dim innerConnection As DbConnectionInternal = Me.InnerConnection
If innerConnection.HasEnlistedTransaction Then
Throw ADP.TransactionPresent
End If
innerConnection.EnlistTransaction(transaction)
GC.KeepAlive(Me)
End Sub
Friend Function GetBytes(ByVal value As String, ByVal useNationalCharacterSet As Boolean) As Byte()
Return Me.GetOpenInternalConnection.GetBytes(value, useNationalCharacterSet)
End Function
Private Function GetMetaDataFactory(ByVal internalConnection As DbConnectionInternal) As DbMetaDataFactory
Return Me.ConnectionFactory.GetMetaDataFactory(Me._poolGroup, internalConnection)
End Function
Friend Function GetMetaDataFactoryInternal(ByVal internalConnection As DbConnectionInternal) As DbMetaDataFactory
Return Me.GetMetaDataFactory(internalConnection)
End Function
Friend Function GetOpenInternalConnection() As OracleInternalConnection
Dim innerConnection As DbConnectionInternal = Me.InnerConnection
If Not TypeOf innerConnection Is OracleInternalConnection Then
Throw ADP.ClosedConnectionError
End If
Return TryCast(innerConnection,OracleInternalConnection)
End Function
Public Overrides Function GetSchema() As DataTable
Return Me.GetSchema(DbMetaDataCollectionNames.MetaDataCollections, Nothing)
End Function
Public Overrides Function GetSchema(ByVal collectionName As String) As DataTable
Return Me.GetSchema(collectionName, Nothing)
End Function
Public Overrides Function GetSchema(ByVal collectionName As String, ByVal restrictionValues As String()) As DataTable
OracleConnection.ExecutePermission.Demand
Return Me.InnerConnection.GetSchema(Me.ConnectionFactory, Me.PoolGroup, Me, collectionName, restrictionValues)
End Function
Friend Function GetScratchBuffer(ByVal minSize As Integer) As NativeBuffer
Return Me.GetOpenInternalConnection.GetScratchBuffer(minSize)
End Function
Friend Function GetString(ByVal bytearray As Byte()) As String
Return Me.GetOpenInternalConnection.GetString(bytearray)
End Function
Friend Function GetString(ByVal bytearray As Byte(), ByVal useNationalCharacterSet As Boolean) As String
Return Me.GetOpenInternalConnection.GetString(bytearray, useNationalCharacterSet)
End Function
Friend Sub NotifyWeakReference(ByVal message As Integer)
Me.InnerConnection.NotifyWeakReference(message)
End Sub
Friend Sub OnInfoMessage(ByVal infoMessageEvent As OracleInfoMessageEventArgs)
Dim handler As OracleInfoMessageEventHandler = DirectCast(MyBase.Events.Item(OracleConnection.EventInfoMessage), OracleInfoMessageEventHandler)
If (Not handler Is Nothing) Then
handler.Invoke(Me, infoMessageEvent)
End If
End Sub
Public Overrides Sub Open()
Me.InnerConnection.OpenConnection(Me, Me.ConnectionFactory)
Dim innerConnection As OracleInternalConnection = TryCast(Me.InnerConnection,OracleInternalConnection)
If (Not innerConnection Is Nothing) Then
innerConnection.FireDeferredInfoMessageEvents(Me)
End If
End Sub
Friend Sub PermissionDemand()
Dim poolGroup As DbConnectionPoolGroup = Me.PoolGroup
Dim options As DbConnectionOptions = IIf((Not poolGroup Is Nothing), poolGroup.ConnectionOptions, Nothing)
If ((options Is Nothing) OrElse options.IsEmpty) Then
Throw ADP.NoConnectionString
End If
Me.UserConnectionOptions.DemandPermission
End Sub
Friend Sub RemoveWeakReference(ByVal value As Object)
Me.InnerConnection.RemoveWeakReference(value)
End Sub
Friend Sub Rollback()
Dim innerConnection As OracleInternalConnection = TryCast(Me.InnerConnection,OracleInternalConnection)
If (Not innerConnection Is Nothing) Then
innerConnection.Rollback
End If
End Sub
Friend Sub RollbackDeadTransaction()
Me.GetOpenInternalConnection.RollbackDeadTransaction
End Sub
Friend Sub SetInnerConnectionEvent(ByVal [to] As DbConnectionInternal)
Dim originalState As ConnectionState = (Me._innerConnection.State And ConnectionState.Open)
Dim currentState As ConnectionState = ([to].State And ConnectionState.Open)
If ((originalState <> currentState) AndAlso (currentState = ConnectionState.Closed)) Then
Me._closeCount += 1
End If
Me._innerConnection = [to]
If ((originalState = ConnectionState.Closed) AndAlso (ConnectionState.Open = currentState)) Then
Me.OnStateChange(DbConnectionInternal.StateChangeOpen)
ElseIf ((ConnectionState.Open = originalState) AndAlso (currentState = ConnectionState.Closed)) Then
Me.OnStateChange(DbConnectionInternal.StateChangeClosed)
ElseIf (originalState <> currentState) Then
Me.OnStateChange(New StateChangeEventArgs(originalState, currentState))
End If
End Sub
Friend Function SetInnerConnectionFrom(ByVal [to] As DbConnectionInternal, ByVal from As DbConnectionInternal) As Boolean
Return (from Is Interlocked.CompareExchange(Of DbConnectionInternal)((Me._innerConnection), [to], from))
End Function
Friend Sub SetInnerConnectionTo(ByVal [to] As DbConnectionInternal)
Me._innerConnection = [to]
End Sub
Private Function System.ICloneable.Clone() As Object Implements ICloneable.Clone
Dim connection As New OracleConnection(Me)
Bid.Trace("<ora.OracleConnection.Clone|API> %d#, clone=%d#" & ChrW(10), Me.ObjectID, connection.ObjectID)
Return connection
End Function
<Conditional("DEBUG")> _
Friend Shared Sub VerifyExecutePermission()
Try
OracleConnection.ExecutePermission.Demand
Catch exception1 As SecurityException
Throw
End Try
End Sub
' Properties
Friend ReadOnly Property CloseCount As Integer
Get
Return Me._closeCount
End Get
End Property
Friend ReadOnly Property ConnectionFactory As DbConnectionFactory
Get
Return OracleConnection._connectionFactory
End Get
End Property
Friend ReadOnly Property ConnectionOptions As DbConnectionOptions
Get
Dim poolGroup As DbConnectionPoolGroup = Me.PoolGroup
If (poolGroup Is Nothing) Then
Return Nothing
End If
Return poolGroup.ConnectionOptions
End Get
End Property
<ResDescription("OracleConnection_ConnectionString"), Editor("Microsoft.VSDesigner.Data.Oracle.Design.OracleConnectionStringEditor, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), DefaultValue(""), ResCategory("OracleCategory_Data"), RefreshProperties(RefreshProperties.All), RecommendedAsConfigurable(True)> _
Public Overrides Property ConnectionString As String
Get
Return Me.ConnectionString_Get
End Get
Set(ByVal value As String)
Me.ConnectionString_Set(value)
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Never), Browsable(False)> _
Public Overrides ReadOnly Property ConnectionTimeout As Integer
Get
Return 0
End Get
End Property
<EditorBrowsable(EditorBrowsableState.Never), Browsable(False)> _
Public Overrides ReadOnly Property Database As String
Get
Return String.Empty
End Get
End Property
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescription("OracleConnection_DataSource"), Browsable(False)> _
Public Overrides ReadOnly Property DataSource As String
Get
Dim connectionOptions As OracleConnectionString = DirectCast(Me.ConnectionOptions, OracleConnectionString)
Dim dataSource As String = String.Empty
If (Not connectionOptions Is Nothing) Then
dataSource = connectionOptions.DataSource
End If
Return dataSource
End Get
End Property
Friend ReadOnly Property EnvironmentHandle As OciEnvironmentHandle
Get
Return Me.GetOpenInternalConnection.EnvironmentHandle
End Get
End Property
Friend ReadOnly Property ErrorHandle As OciErrorHandle
Get
Return Me.GetOpenInternalConnection.ErrorHandle
End Get
End Property
Friend ReadOnly Property HasTransaction As Boolean
Get
Return Me.GetOpenInternalConnection.HasTransaction
End Get
End Property
Friend ReadOnly Property InnerConnection As DbConnectionInternal
Get
Return Me._innerConnection
End Get
End Property
Friend Property PoolGroup As DbConnectionPoolGroup
Get
Return Me._poolGroup
End Get
Set(ByVal value As DbConnectionPoolGroup)
Me._poolGroup = value
End Set
End Property
Friend ReadOnly Property ServerTimeZoneAdjustmentToUTC As TimeSpan
Get
Return Me.GetOpenInternalConnection.GetServerTimeZoneAdjustmentToUTC(Me)
End Get
End Property
<Browsable(False), ResDescription("OracleConnection_ServerVersion"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overrides ReadOnly Property ServerVersion As String
Get
Return Me.GetOpenInternalConnection.ServerVersion
End Get
End Property
Friend ReadOnly Property ServerVersionAtLeastOracle8 As Boolean
Get
Return Me.GetOpenInternalConnection.ServerVersionAtLeastOracle8
End Get
End Property
Friend ReadOnly Property ServerVersionAtLeastOracle9i As Boolean
Get
Return Me.GetOpenInternalConnection.ServerVersionAtLeastOracle9i
End Get
End Property
Friend ReadOnly Property ServiceContextHandle As OciServiceContextHandle
Get
Return Me.GetOpenInternalConnection.ServiceContextHandle
End Get
End Property
<ResDescription("DbConnection_State"), Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overrides ReadOnly Property State As ConnectionState
Get
Return Me.InnerConnection.State
End Get
End Property
Friend ReadOnly Property Transaction As OracleTransaction
Get
Return Me.GetOpenInternalConnection.Transaction
End Get
End Property
Friend Property TransactionState As TransactionState
Get
Return Me.GetOpenInternalConnection.TransactionState
End Get
Set(ByVal value As TransactionState)
Me.GetOpenInternalConnection.TransactionState = value
End Set
End Property
Friend ReadOnly Property UnicodeEnabled As Boolean
Get
Return Me.GetOpenInternalConnection.UnicodeEnabled
End Get
End Property
Friend ReadOnly Property UserConnectionOptions As DbConnectionOptions
Get
Return Me._userConnectionOptions
End Get
End Property
' Fields
Private _closeCount As Integer
Private Shared ReadOnly _connectionFactory As DbConnectionFactory = OracleConnectionFactory.SingletonInstance
Private _innerConnection As DbConnectionInternal
Private Shared _objectTypeCount As Integer
Private _poolGroup As DbConnectionPoolGroup
Private _userConnectionOptions As DbConnectionOptions
Private Shared ReadOnly EventInfoMessage As Object = New Object
Friend Shared ReadOnly ExecutePermission As CodeAccessPermission = OracleConnection.CreateExecutePermission
Friend ReadOnly ObjectID As Integer
End Class
End Namespace