Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ComplexTypeEmitter.cs
- Number.cs
- List.cs
- DataColumnMappingCollection.cs
- RefExpr.cs
- VisualStyleTypesAndProperties.cs
- UpdateException.cs
- HtmlTableCellCollection.cs
- ClrProviderManifest.cs
- DbDataSourceEnumerator.cs
- InsufficientMemoryException.cs
- ReverseInheritProperty.cs
- TagPrefixCollection.cs
- StoryFragments.cs
- ToolStripComboBox.cs
- Profiler.cs
- ProfilePropertyMetadata.cs
- _PooledStream.cs
- Utils.cs
- FrameworkElementAutomationPeer.cs
- RtfFormatStack.cs
- WindowsListViewItem.cs
- DesignUtil.cs
- MediaTimeline.cs
- ExternalException.cs
- TypeConverter.cs
- EnumValidator.cs
- Propagator.Evaluator.cs
- PageWrapper.cs
- TransactionInformation.cs
- MediaScriptCommandRoutedEventArgs.cs
- EndpointDispatcher.cs
- X509CertificateStore.cs
- KeyValuePairs.cs
- IResourceProvider.cs
- NullRuntimeConfig.cs
- ReflectionPermission.cs
- DesignTimeValidationFeature.cs
- Encoder.cs
- TransactionFilter.cs
- XmlArrayItemAttributes.cs
- StylusDownEventArgs.cs
- AutoGeneratedField.cs
- X509Certificate2Collection.cs
- VSWCFServiceContractGenerator.cs
- DbModificationClause.cs
- XamlNamespaceHelper.cs
- SecurityRuntime.cs
- SqlCacheDependencySection.cs
- InboundActivityHelper.cs
- HashCodeCombiner.cs
- FilteredDataSetHelper.cs
- HighlightVisual.cs
- CultureInfoConverter.cs
- ConfigurationManagerInternalFactory.cs
- RequiredFieldValidator.cs
- ContentWrapperAttribute.cs
- QualifiedCellIdBoolean.cs
- TextFormatterImp.cs
- ComponentManagerBroker.cs
- MD5CryptoServiceProvider.cs
- XmlWrappingReader.cs
- WindowsSpinner.cs
- BooleanSwitch.cs
- ControlUtil.cs
- Pts.cs
- JavaScriptString.cs
- Trace.cs
- MemoryFailPoint.cs
- Timer.cs
- ClientSettingsProvider.cs
- ThousandthOfEmRealDoubles.cs
- RadioButton.cs
- FreezableOperations.cs
- FileInfo.cs
- MailBnfHelper.cs
- HScrollProperties.cs
- HttpConfigurationContext.cs
- ColorContext.cs
- ToolBar.cs
- WorkflowViewManager.cs
- TypefaceMetricsCache.cs
- ApplicationServiceManager.cs
- RenderDataDrawingContext.cs
- AccessibleObject.cs
- DecimalAnimationUsingKeyFrames.cs
- WhitespaceSignificantCollectionAttribute.cs
- WebZoneDesigner.cs
- SqlTypeSystemProvider.cs
- MaskPropertyEditor.cs
- propertyentry.cs
- MethodBuilderInstantiation.cs
- SafeCryptoHandles.cs
- DataTableTypeConverter.cs
- GeometryDrawing.cs
- GridEntry.cs
- ZipIOExtraFieldPaddingElement.cs
- DateTimeFormatInfoScanner.cs
- BitmapSource.cs
- CssTextWriter.cs