Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / ProviderBase / DbConnectionHelper.cs / 1305376 / DbConnectionHelper.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace NAMESPACE { using System; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Data.ProviderBase; using System.Diagnostics; using System.Globalization; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Threading; using SysTx = System.Transactions; using System.Diagnostics.CodeAnalysis; public sealed partial class CONNECTIONOBJECTNAME : DbConnection { private static readonly DbConnectionFactory _connectionFactory = CONNECTIONFACTORYOBJECTNAME; internal static readonly System.Security.CodeAccessPermission ExecutePermission = CONNECTIONOBJECTNAME.CreateExecutePermission(); private DbConnectionOptions _userConnectionOptions; private DbConnectionPoolGroup _poolGroup; private DbConnectionInternal _innerConnection; private int _closeCount; // used to distinguish between different uses of this object, so we don't have to maintain a list of it's children private static int _objectTypeCount; // Bid counter internal readonly int ObjectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); public CONNECTIONOBJECTNAME() : base() { GC.SuppressFinalize(this); _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } // Copy Constructor private void CopyFrom(CONNECTIONOBJECTNAME connection) { // V1.2.3300 ADP.CheckArgumentNull(connection, "connection"); _userConnectionOptions = connection.UserConnectionOptions; _poolGroup = connection.PoolGroup; // SQLBU 432115 // Match the original connection's behavior for whether the connection was never opened, // but ensure Clone is in the closed state. if (DbConnectionClosedNeverOpened.SingletonInstance == connection._innerConnection) { _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } else { _innerConnection = DbConnectionClosedPreviouslyOpened.SingletonInstance; } } ///We use the _closeCount to avoid having to know about all our /// children; instead of keeping a collection of all the objects that /// would be affected by a close, we simply increment the _closeCount /// and have each of our children check to see if they're "orphaned" /// internal int CloseCount { get { return _closeCount; } } internal DbConnectionFactory ConnectionFactory { get { return _connectionFactory; } } internal DbConnectionOptions ConnectionOptions { get { System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = PoolGroup; return ((null != poolGroup) ? poolGroup.ConnectionOptions : null); } } private string ConnectionString_Get() { Bid.Trace( "%d#\n", ObjectID); bool hidePassword = InnerConnection.ShouldHidePassword; DbConnectionOptions connectionOptions = UserConnectionOptions; return ((null != connectionOptions) ? connectionOptions.UsersConnectionString(hidePassword) : ""); } private void ConnectionString_Set(string value) { DbConnectionOptions connectionOptions = null; System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = ConnectionFactory.GetConnectionPoolGroup(value, null, ref connectionOptions); DbConnectionInternal connectionInternal = InnerConnection; bool flag = connectionInternal.AllowSetConnectionString; if (flag) { //try { // NOTE: There's a race condition with multiple threads changing // ConnectionString and any thread throws an exception // Closed->Busy: prevent Open during set_ConnectionString flag = SetInnerConnectionFrom(DbConnectionClosedBusy.SingletonInstance, connectionInternal); if (flag) { _userConnectionOptions = connectionOptions; _poolGroup = poolGroup; _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } //} //catch { // // recover from exceptions to avoid sticking in busy state // SetInnerConnectionFrom(connectionInternal, DbConnectionClosedBusy.SingletonInstance); // throw; //} } if (!flag) { throw ADP.OpenConnectionPropertySet(ADP.ConnectionString, connectionInternal.State); } if (Bid.TraceOn) { string cstr = ((null != connectionOptions) ? connectionOptions.UsersConnectionStringForTrace() : ""); Bid.Trace(" %d#, '%ls'\n", ObjectID, cstr); } } internal DbConnectionInternal InnerConnection { get { return _innerConnection; } } internal System.Data.ProviderBase.DbConnectionPoolGroup PoolGroup { get { return _poolGroup; } set { // when a poolgroup expires and the connection eventually activates, the pool entry will be replaced Debug.Assert(null != value, "null poolGroup"); _poolGroup = value; } } [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), RESNAMESPACE.ResDescriptionAttribute(Res.DbConnection_State), ] override public ConnectionState State { get { return InnerConnection.State; } } internal DbConnectionOptions UserConnectionOptions { get { return _userConnectionOptions; } } // Open->ClosedPreviouslyOpened, and doom the internal connection too... [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal void Abort(Exception e) { DbConnectionInternal innerConnection = _innerConnection; // Should not cause memory allocation... if (ConnectionState.Open == innerConnection.State) { Interlocked.CompareExchange(ref _innerConnection, DbConnectionClosedPreviouslyOpened.SingletonInstance, innerConnection); innerConnection.DoomThisConnection(); } // NOTE: we put the tracing last, because the ToString() calls (and // the Bid.Trace, for that matter) have no reliability contract and // will end the reliable try... if (e is OutOfMemoryException) { Bid.Trace(" %d#, Aborting operation due to asynchronous exception: %ls\n", ObjectID, "OutOfMemory"); } else { Bid.Trace(" %d#, Aborting operation due to asynchronous exception: %ls\n", ObjectID, e.ToString()); } } internal void AddWeakReference(object value, int tag) { InnerConnection.AddWeakReference(value, tag); } // suppress this message - we cannot use SafeHandle here. Also, see notes in the code (VSTFDEVDIV# 560355) [SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive")] override protected DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#, isolationLevel=%d{ds.IsolationLevel}", ObjectID, (int)isolationLevel); try { DbTransaction transaction = InnerConnection.BeginTransaction(isolationLevel); // VSTFDEVDIV# 560355 - InnerConnection doesn't maintain a ref on the outer connection (this) and // subsequently leaves open the possibility that the outer connection could be GC'ed before the SqlTransaction // is fully hooked up (leaving a SqlTransaction with a null connection property). Ensure that this is reachable // until the completion of BeginTransaction with KeepAlive GC.KeepAlive ( this ); return transaction; } finally { Bid.ScopeLeave(ref hscp); } } override protected DbCommand CreateDbCommand() { DbCommand command = null; IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); try { DbProviderFactory providerFactory = ConnectionFactory.ProviderFactory; command = providerFactory.CreateCommand(); command.Connection = this; } finally { Bid.ScopeLeave(ref hscp); } return command; } private static System.Security.CodeAccessPermission CreateExecutePermission() { #if ORACLE OraclePermission p = new OraclePermission(System.Security.Permissions.PermissionState.None); p.Add(String.Empty, String.Empty, KeyRestrictionBehavior.AllowOnly); return p; #else DBDataPermission p = (DBDataPermission)CONNECTIONFACTORYOBJECTNAME.ProviderFactory.CreatePermission(System.Security.Permissions.PermissionState.None); p.Add(String.Empty, String.Empty, KeyRestrictionBehavior.AllowOnly); return p; #endif } override protected void Dispose(bool disposing) { if (disposing) { _userConnectionOptions = null; _poolGroup= null; Close(); } DisposeMe(disposing); base.Dispose(disposing); // notify base classes } // NOTE: This is just a private helper because OracleClient V1.1 shipped // with a different argument name and it's a breaking change to not use // the same argument names in V2.0 (VB Named Parameter Binding--Ick) private void EnlistDistributedTransactionHelper(System.EnterpriseServices.ITransaction transaction) { System.Security.PermissionSet permissionSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None); permissionSet.AddPermission(CONNECTIONOBJECTNAME.ExecutePermission); // MDAC 81476 permissionSet.AddPermission(new System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)); permissionSet.Demand(); Bid.Trace( " %d#, Connection enlisting in a transaction.\n", ObjectID); SysTx.Transaction indigoTransaction = null; if (null != transaction) { indigoTransaction = SysTx.TransactionInterop.GetTransactionFromDtcTransaction((SysTx.IDtcTransaction)transaction); } // NOTE: since transaction enlistment involves round trips to the // server, we don't want to lock here, we'll handle the race conditions // elsewhere. InnerConnection.EnlistTransaction(indigoTransaction); // NOTE: If this outer connection were to be GC'd while we're // enlisting, the pooler would attempt to reclaim the inner connection // while we're attempting to enlist; not sure how likely that is but // we should consider a GC.KeepAlive(this) here. GC.KeepAlive(this); } override public void EnlistTransaction(SysTx.Transaction transaction) { CONNECTIONOBJECTNAME.ExecutePermission.Demand(); Bid.Trace( " %d#, Connection enlisting in a transaction.\n", ObjectID); // If we're currently enlisted in a transaction and we were called // on the EnlistTransaction method (Whidbey) we're not allowed to // enlist in a different transaction. DbConnectionInternal innerConnection = InnerConnection; // NOTE: since transaction enlistment involves round trips to the // server, we don't want to lock here, we'll handle the race conditions // elsewhere. SysTx.Transaction enlistedTransaction = innerConnection.EnlistedTransaction; if (enlistedTransaction != null) { // Allow calling enlist if already enlisted (no-op) if (enlistedTransaction.Equals(transaction)) { return; } // Allow enlisting in a different transaction if the enlisted transaction has completed. if (enlistedTransaction.TransactionInformation.Status == SysTx.TransactionStatus.Active) { throw ADP.TransactionPresent(); } } innerConnection.EnlistTransaction(transaction); // NOTE: If this outer connection were to be GC'd while we're // enlisting, the pooler would attempt to reclaim the inner connection // while we're attempting to enlist; not sure how likely that is but // we should consider a GC.KeepAlive(this) here. GC.KeepAlive(this); } private DbMetaDataFactory GetMetaDataFactory(DbConnectionInternal internalConnection) { return ConnectionFactory.GetMetaDataFactory(_poolGroup, internalConnection); } internal DbMetaDataFactory GetMetaDataFactoryInternal(DbConnectionInternal internalConnection) { return GetMetaDataFactory(internalConnection); } override public DataTable GetSchema() { return this.GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null); } override public DataTable GetSchema(string collectionName) { return this.GetSchema(collectionName, null); } override public DataTable GetSchema(string collectionName, string[] restrictionValues) { // NOTE: This is virtual because not all providers may choose to support // returning schema data CONNECTIONOBJECTNAME.ExecutePermission.Demand(); return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues); } internal void NotifyWeakReference(int message) { InnerConnection.NotifyWeakReference(message); } internal void PermissionDemand() { Debug.Assert(DbConnectionClosedConnecting.SingletonInstance == _innerConnection, "not connecting"); System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = PoolGroup; DbConnectionOptions connectionOptions = ((null != poolGroup) ? poolGroup.ConnectionOptions : null); if ((null == connectionOptions) || connectionOptions.IsEmpty) { throw ADP.NoConnectionString(); } DbConnectionOptions userConnectionOptions = UserConnectionOptions; Debug.Assert(null != userConnectionOptions, "null UserConnectionOptions"); userConnectionOptions.DemandPermission(); } internal void RemoveWeakReference(object value) { InnerConnection.RemoveWeakReference(value); } // OpenBusy->Closed (previously opened) // Connecting->Open internal void SetInnerConnectionEvent(DbConnectionInternal to) { // Set's the internal connection without verifying that it's a specific value Debug.Assert(null != _innerConnection, "null InnerConnection"); Debug.Assert(null != to, "to null InnerConnection"); ConnectionState originalState = _innerConnection.State & ConnectionState.Open; ConnectionState currentState = to.State & ConnectionState.Open; if ((originalState != currentState) && (ConnectionState.Closed == currentState)) { // Increment the close count whenever we switch to Closed unchecked { _closeCount++; } } _innerConnection = to; if (ConnectionState.Closed == originalState && ConnectionState.Open == currentState) { OnStateChange(DbConnectionInternal.StateChangeOpen); } else if (ConnectionState.Open == originalState && ConnectionState.Closed == currentState) { OnStateChange(DbConnectionInternal.StateChangeClosed); } else { Debug.Assert(false, "unexpected state switch"); if (originalState != currentState) { OnStateChange(new StateChangeEventArgs(originalState, currentState)); } } } // this method is used to securely change state with the resource being // the open connection protected by the connectionstring via a permission demand // Closed->Connecting: prevent set_ConnectionString during Open // Open->OpenBusy: guarantee internal connection is returned to correct pool // Closed->ClosedBusy: prevent Open during set_ConnectionString internal bool SetInnerConnectionFrom(DbConnectionInternal to, DbConnectionInternal from) { // Set's the internal connection, verifying that it's a specific value before doing so. Debug.Assert(null != _innerConnection, "null InnerConnection"); Debug.Assert(null != from, "from null InnerConnection"); Debug.Assert(null != to, "to null InnerConnection"); bool result = (from == Interlocked.CompareExchange (ref _innerConnection, to, from)); return result; } // ClosedBusy->Closed (never opened) // Connecting->Closed (exception during open, return to previous closed state) internal void SetInnerConnectionTo(DbConnectionInternal to) { // Set's the internal connection without verifying that it's a specific value Debug.Assert(null != _innerConnection, "null InnerConnection"); Debug.Assert(null != to, "to null InnerConnection"); _innerConnection = to; } [ConditionalAttribute("DEBUG")] internal static void VerifyExecutePermission() { try { // use this to help validate this code path is only used after the following permission has been previously demanded in the current codepath CONNECTIONOBJECTNAME.ExecutePermission.Demand(); } catch(System.Security.SecurityException) { System.Diagnostics.Debug.Assert(false, "unexpected SecurityException for current codepath"); throw; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace NAMESPACE { using System; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Data.ProviderBase; using System.Diagnostics; using System.Globalization; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Threading; using SysTx = System.Transactions; using System.Diagnostics.CodeAnalysis; public sealed partial class CONNECTIONOBJECTNAME : DbConnection { private static readonly DbConnectionFactory _connectionFactory = CONNECTIONFACTORYOBJECTNAME; internal static readonly System.Security.CodeAccessPermission ExecutePermission = CONNECTIONOBJECTNAME.CreateExecutePermission(); private DbConnectionOptions _userConnectionOptions; private DbConnectionPoolGroup _poolGroup; private DbConnectionInternal _innerConnection; private int _closeCount; // used to distinguish between different uses of this object, so we don't have to maintain a list of it's children private static int _objectTypeCount; // Bid counter internal readonly int ObjectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); public CONNECTIONOBJECTNAME() : base() { GC.SuppressFinalize(this); _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } // Copy Constructor private void CopyFrom(CONNECTIONOBJECTNAME connection) { // V1.2.3300 ADP.CheckArgumentNull(connection, "connection"); _userConnectionOptions = connection.UserConnectionOptions; _poolGroup = connection.PoolGroup; // SQLBU 432115 // Match the original connection's behavior for whether the connection was never opened, // but ensure Clone is in the closed state. if (DbConnectionClosedNeverOpened.SingletonInstance == connection._innerConnection) { _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } else { _innerConnection = DbConnectionClosedPreviouslyOpened.SingletonInstance; } } ///We use the _closeCount to avoid having to know about all our /// children; instead of keeping a collection of all the objects that /// would be affected by a close, we simply increment the _closeCount /// and have each of our children check to see if they're "orphaned" /// internal int CloseCount { get { return _closeCount; } } internal DbConnectionFactory ConnectionFactory { get { return _connectionFactory; } } internal DbConnectionOptions ConnectionOptions { get { System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = PoolGroup; return ((null != poolGroup) ? poolGroup.ConnectionOptions : null); } } private string ConnectionString_Get() { Bid.Trace( "%d#\n", ObjectID); bool hidePassword = InnerConnection.ShouldHidePassword; DbConnectionOptions connectionOptions = UserConnectionOptions; return ((null != connectionOptions) ? connectionOptions.UsersConnectionString(hidePassword) : ""); } private void ConnectionString_Set(string value) { DbConnectionOptions connectionOptions = null; System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = ConnectionFactory.GetConnectionPoolGroup(value, null, ref connectionOptions); DbConnectionInternal connectionInternal = InnerConnection; bool flag = connectionInternal.AllowSetConnectionString; if (flag) { //try { // NOTE: There's a race condition with multiple threads changing // ConnectionString and any thread throws an exception // Closed->Busy: prevent Open during set_ConnectionString flag = SetInnerConnectionFrom(DbConnectionClosedBusy.SingletonInstance, connectionInternal); if (flag) { _userConnectionOptions = connectionOptions; _poolGroup = poolGroup; _innerConnection = DbConnectionClosedNeverOpened.SingletonInstance; } //} //catch { // // recover from exceptions to avoid sticking in busy state // SetInnerConnectionFrom(connectionInternal, DbConnectionClosedBusy.SingletonInstance); // throw; //} } if (!flag) { throw ADP.OpenConnectionPropertySet(ADP.ConnectionString, connectionInternal.State); } if (Bid.TraceOn) { string cstr = ((null != connectionOptions) ? connectionOptions.UsersConnectionStringForTrace() : ""); Bid.Trace(" %d#, '%ls'\n", ObjectID, cstr); } } internal DbConnectionInternal InnerConnection { get { return _innerConnection; } } internal System.Data.ProviderBase.DbConnectionPoolGroup PoolGroup { get { return _poolGroup; } set { // when a poolgroup expires and the connection eventually activates, the pool entry will be replaced Debug.Assert(null != value, "null poolGroup"); _poolGroup = value; } } [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), RESNAMESPACE.ResDescriptionAttribute(Res.DbConnection_State), ] override public ConnectionState State { get { return InnerConnection.State; } } internal DbConnectionOptions UserConnectionOptions { get { return _userConnectionOptions; } } // Open->ClosedPreviouslyOpened, and doom the internal connection too... [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal void Abort(Exception e) { DbConnectionInternal innerConnection = _innerConnection; // Should not cause memory allocation... if (ConnectionState.Open == innerConnection.State) { Interlocked.CompareExchange(ref _innerConnection, DbConnectionClosedPreviouslyOpened.SingletonInstance, innerConnection); innerConnection.DoomThisConnection(); } // NOTE: we put the tracing last, because the ToString() calls (and // the Bid.Trace, for that matter) have no reliability contract and // will end the reliable try... if (e is OutOfMemoryException) { Bid.Trace(" %d#, Aborting operation due to asynchronous exception: %ls\n", ObjectID, "OutOfMemory"); } else { Bid.Trace(" %d#, Aborting operation due to asynchronous exception: %ls\n", ObjectID, e.ToString()); } } internal void AddWeakReference(object value, int tag) { InnerConnection.AddWeakReference(value, tag); } // suppress this message - we cannot use SafeHandle here. Also, see notes in the code (VSTFDEVDIV# 560355) [SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive")] override protected DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#, isolationLevel=%d{ds.IsolationLevel}", ObjectID, (int)isolationLevel); try { DbTransaction transaction = InnerConnection.BeginTransaction(isolationLevel); // VSTFDEVDIV# 560355 - InnerConnection doesn't maintain a ref on the outer connection (this) and // subsequently leaves open the possibility that the outer connection could be GC'ed before the SqlTransaction // is fully hooked up (leaving a SqlTransaction with a null connection property). Ensure that this is reachable // until the completion of BeginTransaction with KeepAlive GC.KeepAlive ( this ); return transaction; } finally { Bid.ScopeLeave(ref hscp); } } override protected DbCommand CreateDbCommand() { DbCommand command = null; IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); try { DbProviderFactory providerFactory = ConnectionFactory.ProviderFactory; command = providerFactory.CreateCommand(); command.Connection = this; } finally { Bid.ScopeLeave(ref hscp); } return command; } private static System.Security.CodeAccessPermission CreateExecutePermission() { #if ORACLE OraclePermission p = new OraclePermission(System.Security.Permissions.PermissionState.None); p.Add(String.Empty, String.Empty, KeyRestrictionBehavior.AllowOnly); return p; #else DBDataPermission p = (DBDataPermission)CONNECTIONFACTORYOBJECTNAME.ProviderFactory.CreatePermission(System.Security.Permissions.PermissionState.None); p.Add(String.Empty, String.Empty, KeyRestrictionBehavior.AllowOnly); return p; #endif } override protected void Dispose(bool disposing) { if (disposing) { _userConnectionOptions = null; _poolGroup= null; Close(); } DisposeMe(disposing); base.Dispose(disposing); // notify base classes } // NOTE: This is just a private helper because OracleClient V1.1 shipped // with a different argument name and it's a breaking change to not use // the same argument names in V2.0 (VB Named Parameter Binding--Ick) private void EnlistDistributedTransactionHelper(System.EnterpriseServices.ITransaction transaction) { System.Security.PermissionSet permissionSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None); permissionSet.AddPermission(CONNECTIONOBJECTNAME.ExecutePermission); // MDAC 81476 permissionSet.AddPermission(new System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)); permissionSet.Demand(); Bid.Trace( " %d#, Connection enlisting in a transaction.\n", ObjectID); SysTx.Transaction indigoTransaction = null; if (null != transaction) { indigoTransaction = SysTx.TransactionInterop.GetTransactionFromDtcTransaction((SysTx.IDtcTransaction)transaction); } // NOTE: since transaction enlistment involves round trips to the // server, we don't want to lock here, we'll handle the race conditions // elsewhere. InnerConnection.EnlistTransaction(indigoTransaction); // NOTE: If this outer connection were to be GC'd while we're // enlisting, the pooler would attempt to reclaim the inner connection // while we're attempting to enlist; not sure how likely that is but // we should consider a GC.KeepAlive(this) here. GC.KeepAlive(this); } override public void EnlistTransaction(SysTx.Transaction transaction) { CONNECTIONOBJECTNAME.ExecutePermission.Demand(); Bid.Trace( " %d#, Connection enlisting in a transaction.\n", ObjectID); // If we're currently enlisted in a transaction and we were called // on the EnlistTransaction method (Whidbey) we're not allowed to // enlist in a different transaction. DbConnectionInternal innerConnection = InnerConnection; // NOTE: since transaction enlistment involves round trips to the // server, we don't want to lock here, we'll handle the race conditions // elsewhere. SysTx.Transaction enlistedTransaction = innerConnection.EnlistedTransaction; if (enlistedTransaction != null) { // Allow calling enlist if already enlisted (no-op) if (enlistedTransaction.Equals(transaction)) { return; } // Allow enlisting in a different transaction if the enlisted transaction has completed. if (enlistedTransaction.TransactionInformation.Status == SysTx.TransactionStatus.Active) { throw ADP.TransactionPresent(); } } innerConnection.EnlistTransaction(transaction); // NOTE: If this outer connection were to be GC'd while we're // enlisting, the pooler would attempt to reclaim the inner connection // while we're attempting to enlist; not sure how likely that is but // we should consider a GC.KeepAlive(this) here. GC.KeepAlive(this); } private DbMetaDataFactory GetMetaDataFactory(DbConnectionInternal internalConnection) { return ConnectionFactory.GetMetaDataFactory(_poolGroup, internalConnection); } internal DbMetaDataFactory GetMetaDataFactoryInternal(DbConnectionInternal internalConnection) { return GetMetaDataFactory(internalConnection); } override public DataTable GetSchema() { return this.GetSchema(DbMetaDataCollectionNames.MetaDataCollections, null); } override public DataTable GetSchema(string collectionName) { return this.GetSchema(collectionName, null); } override public DataTable GetSchema(string collectionName, string[] restrictionValues) { // NOTE: This is virtual because not all providers may choose to support // returning schema data CONNECTIONOBJECTNAME.ExecutePermission.Demand(); return InnerConnection.GetSchema(ConnectionFactory, PoolGroup, this, collectionName, restrictionValues); } internal void NotifyWeakReference(int message) { InnerConnection.NotifyWeakReference(message); } internal void PermissionDemand() { Debug.Assert(DbConnectionClosedConnecting.SingletonInstance == _innerConnection, "not connecting"); System.Data.ProviderBase.DbConnectionPoolGroup poolGroup = PoolGroup; DbConnectionOptions connectionOptions = ((null != poolGroup) ? poolGroup.ConnectionOptions : null); if ((null == connectionOptions) || connectionOptions.IsEmpty) { throw ADP.NoConnectionString(); } DbConnectionOptions userConnectionOptions = UserConnectionOptions; Debug.Assert(null != userConnectionOptions, "null UserConnectionOptions"); userConnectionOptions.DemandPermission(); } internal void RemoveWeakReference(object value) { InnerConnection.RemoveWeakReference(value); } // OpenBusy->Closed (previously opened) // Connecting->Open internal void SetInnerConnectionEvent(DbConnectionInternal to) { // Set's the internal connection without verifying that it's a specific value Debug.Assert(null != _innerConnection, "null InnerConnection"); Debug.Assert(null != to, "to null InnerConnection"); ConnectionState originalState = _innerConnection.State & ConnectionState.Open; ConnectionState currentState = to.State & ConnectionState.Open; if ((originalState != currentState) && (ConnectionState.Closed == currentState)) { // Increment the close count whenever we switch to Closed unchecked { _closeCount++; } } _innerConnection = to; if (ConnectionState.Closed == originalState && ConnectionState.Open == currentState) { OnStateChange(DbConnectionInternal.StateChangeOpen); } else if (ConnectionState.Open == originalState && ConnectionState.Closed == currentState) { OnStateChange(DbConnectionInternal.StateChangeClosed); } else { Debug.Assert(false, "unexpected state switch"); if (originalState != currentState) { OnStateChange(new StateChangeEventArgs(originalState, currentState)); } } } // this method is used to securely change state with the resource being // the open connection protected by the connectionstring via a permission demand // Closed->Connecting: prevent set_ConnectionString during Open // Open->OpenBusy: guarantee internal connection is returned to correct pool // Closed->ClosedBusy: prevent Open during set_ConnectionString internal bool SetInnerConnectionFrom(DbConnectionInternal to, DbConnectionInternal from) { // Set's the internal connection, verifying that it's a specific value before doing so. Debug.Assert(null != _innerConnection, "null InnerConnection"); Debug.Assert(null != from, "from null InnerConnection"); Debug.Assert(null != to, "to null InnerConnection"); bool result = (from == Interlocked.CompareExchange (ref _innerConnection, to, from)); return result; } // ClosedBusy->Closed (never opened) // Connecting->Closed (exception during open, return to previous closed state) internal void SetInnerConnectionTo(DbConnectionInternal to) { // Set's the internal connection without verifying that it's a specific value Debug.Assert(null != _innerConnection, "null InnerConnection"); Debug.Assert(null != to, "to null InnerConnection"); _innerConnection = to; } [ConditionalAttribute("DEBUG")] internal static void VerifyExecutePermission() { try { // use this to help validate this code path is only used after the following permission has been previously demanded in the current codepath CONNECTIONOBJECTNAME.ExecutePermission.Demand(); } catch(System.Security.SecurityException) { System.Diagnostics.Debug.Assert(false, "unexpected SecurityException for current codepath"); throw; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AllMembershipCondition.cs
- MSAAEventDispatcher.cs
- Win32.cs
- DoubleStorage.cs
- DbConnectionInternal.cs
- ListViewItemSelectionChangedEvent.cs
- BitArray.cs
- FileDialogCustomPlace.cs
- EntityContainerEntitySetDefiningQuery.cs
- AnnotationHighlightLayer.cs
- CharEnumerator.cs
- SiteMapNodeCollection.cs
- HtmlWindowCollection.cs
- DragDrop.cs
- ParseNumbers.cs
- PenLineJoinValidation.cs
- FilterElement.cs
- PartialList.cs
- Menu.cs
- TreeNodeClickEventArgs.cs
- X509Utils.cs
- DataSourceXmlSerializationAttribute.cs
- PaperSource.cs
- RootProfilePropertySettingsCollection.cs
- Delay.cs
- BitStack.cs
- BindingRestrictions.cs
- CompilerGlobalScopeAttribute.cs
- SecurityUtils.cs
- TabControlCancelEvent.cs
- Triplet.cs
- XmlSchemaImporter.cs
- DoubleAnimation.cs
- MultiDataTrigger.cs
- ClientScriptManager.cs
- Brush.cs
- XmlSchemaValidator.cs
- SoapSchemaMember.cs
- MatrixConverter.cs
- XmlSchemaAttribute.cs
- InvokeProviderWrapper.cs
- XmlDataSourceNodeDescriptor.cs
- DbFunctionCommandTree.cs
- AutomationPropertyInfo.cs
- StaticDataManager.cs
- VersionPair.cs
- columnmapfactory.cs
- SubtreeProcessor.cs
- ProxyElement.cs
- StyleSelector.cs
- ResourceBinder.cs
- HtmlInputHidden.cs
- CriticalExceptions.cs
- Binding.cs
- ColorInterpolationModeValidation.cs
- MimeTypePropertyAttribute.cs
- ResourceDescriptionAttribute.cs
- UseManagedPresentationElement.cs
- BitmapPalettes.cs
- ZipIOBlockManager.cs
- AdCreatedEventArgs.cs
- InternalControlCollection.cs
- DesignerActionListCollection.cs
- EventDescriptorCollection.cs
- RunClient.cs
- EmptyImpersonationContext.cs
- PropertyConverter.cs
- PartialList.cs
- WpfGeneratedKnownProperties.cs
- DetailsViewModeEventArgs.cs
- ConnectionManagementSection.cs
- FileLevelControlBuilderAttribute.cs
- FormViewPagerRow.cs
- ISAPIRuntime.cs
- MenuTracker.cs
- WriterOutput.cs
- ObjectQueryState.cs
- ListItemsPage.cs
- MetadataArtifactLoader.cs
- MultipleViewProviderWrapper.cs
- ActivationProxy.cs
- SqlClientWrapperSmiStreamChars.cs
- Base64Decoder.cs
- WebHeaderCollection.cs
- mediapermission.cs
- BrowserDefinition.cs
- ThreadStartException.cs
- UserCancellationException.cs
- SqlResolver.cs
- FontInfo.cs
- InkCanvasSelectionAdorner.cs
- webclient.cs
- ListBindingHelper.cs
- PreviewPrintController.cs
- ConnectionPoolManager.cs
- TaskHelper.cs
- DataList.cs
- COM2EnumConverter.cs
- BindingBase.cs
- Subtree.cs