public interface IDbConnection : IDisposable
{
void Close();
void Open();
IDbTransaction BeginTransaction();
IDbTransaction BeginTransaction(IsolationLevel il);
string ConnectionString { get; set; }
int ConnectionTimeout { get; }
string Database { get; }
ConnectionState State { get; }
void ChangeDatabase(string databaseName);
IDbCommand CreateCommand();
}
public abstract class DbConnection : Component, IDbConnection
{
private StateChangeEventHandler _stateChangeEventHandler;
protected DbConnection() : base()
{
}
abstract protected DbTransaction BeginDbTransaction(IsolationLevel isolationLevel);
public DbTransaction BeginTransaction()
{
return BeginDbTransaction(IsolationLevel.Unspecified);
}
public DbTransaction BeginTransaction(IsolationLevel isolationLevel)
{
return BeginDbTransaction(isolationLevel);
}
IDbTransaction IDbConnection.BeginTransaction()
{
return BeginDbTransaction(IsolationLevel.Unspecified);
}
IDbTransaction IDbConnection.BeginTransaction(IsolationLevel isolationLevel)
{
return BeginDbTransaction(isolationLevel);
}
abstract protected DbCommand CreateDbCommand();
abstract public void Close();
abstract public void Open();
public Task OpenAsync()
{
return OpenAsync(CancellationToken.None);
}
public virtual Task OpenAsync(CancellationToken cancellationToken) {
TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();
if (cancellationToken.IsCancellationRequested) {
taskCompletionSource.SetCanceled();
}
else {
try
{
Open();
taskCompletionSource.SetResult(null);
}
catch (Exception e) {
taskCompletionSource.SetException(e);
}
}
return taskCompletionSource.Task;
}
}
public sealed partial class SqlConnection : DbConnection, ICloneable
{
public SqlConnection(string connectionString)
: this(connectionString, null)
{
}
new public SqlTransaction BeginTransaction()
{
return BeginTransaction(IsolationLevel.Unspecified, null);
}
new public SqlTransaction BeginTransaction(IsolationLevel iso)
{
return BeginTransaction(iso, null);
}
public SqlTransaction BeginTransaction(string transactionName)
{
return BeginTransaction(IsolationLevel.Unspecified, transactionName);
}
static public void ClearAllPools()
{
(new SqlClientPermission(PermissionState.Unrestricted)).Demand();
SqlConnectionFactory.SingletonInstance.ClearAllPools();
}
static public void ClearPool(SqlConnection connection)
{
ADP.CheckArgumentNull(connection, "connection");
DbConnectionOptions connectionOptions = connection.UserConnectionOptions;
if (null != connectionOptions)
{
connectionOptions.DemandPermission();
if (connection.IsContextConnection)
{
throw SQL.NotAvailableOnContextConnection();
}
SqlConnectionFactory.SingletonInstance.ClearPool(connection);
}
}
override public void Close()
{
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#", ObjectID);
Bid.CorrelationTrace("<sc.SqlConnection.Close|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
try
{
SqlStatistics statistics = null;
TdsParser bestEffortCleanupTarget = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
#if DEBUG
TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection();
RuntimeHelpers.PrepareConstrainedRegions();
try {
tdsReliabilitySection.Start();
#else
{
#endif //DEBUG
bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this);
statistics = SqlStatistics.StartTimer(Statistics);
Task reconnectTask = _currentReconnectionTask;
if (reconnectTask != null && !reconnectTask.IsCompleted)
{
CancellationTokenSource cts = _reconnectionCancellationSource;
if (cts != null)
{
cts.Cancel();
}
AsyncHelper.WaitForCompletion(reconnectTask, 0, null, rethrowExceptions: false);
if (State != ConnectionState.Open)
{
OnStateChange(DbConnectionInternal.StateChangeClosed);
}
}
CancelOpenAndWait();
CloseInnerConnection();
GC.SuppressFinalize(this);
if (null != Statistics)
{
ADP.TimerCurrent(out _statistics._closeTimestamp);
}
}
#if DEBUG
finally {
tdsReliabilitySection.Stop();
}
#endif //DEBUG
}
catch (System.OutOfMemoryException e)
{
Abort(e);
throw;
}
catch (System.StackOverflowException e)
{
Abort(e);
throw;
}
catch (System.Threading.ThreadAbortException e)
{
Abort(e);
SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget);
throw;
}
finally
{
SqlStatistics.StopTimer(statistics);
}
}
finally
{
SqlDebugContext sdc = _sdc;
_sdc = null;
Bid.ScopeLeave(ref hscp);
if (sdc != null)
{
sdc.Dispose();
}
}
}
private void DisposeMe(bool disposing)
{
_credential = null;
_accessToken = null;
if (!disposing)
{
var innerConnection = (InnerConnection as SqlInternalConnectionTds);
if ((innerConnection != null) && (!innerConnection.ConnectionOptions.Pooling))
{
var parser = innerConnection.Parser;
if ((parser != null) && (parser._physicalStateObj != null))
{
parser._physicalStateObj.DecrementPendingCallbacks(release: false);
}
}
}
}
override public void Open()
{
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Open|API> %d#", ObjectID);
Bid.CorrelationTrace("<sc.SqlConnection.Open|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
try
{
if (StatisticsEnabled)
{
if (null == _statistics)
{
_statistics = new SqlStatistics();
}
else
{
_statistics.ContinueOnNewConnection();
}
}
SqlStatistics statistics = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
statistics = SqlStatistics.StartTimer(Statistics);
if (!TryOpen(null))
{
throw ADP.InternalError(ADP.InternalErrorCode.SynchronousConnectReturnedPending);
}
}
finally
{
SqlStatistics.StopTimer(statistics);
}
}
finally
{
Bid.ScopeLeave(ref hscp);
}
}
public override Task OpenAsync(CancellationToken cancellationToken)
{
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.OpenAsync|API> %d#", ObjectID);
Bid.CorrelationTrace("<sc.SqlConnection.OpenAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
try
{
if (StatisticsEnabled)
{
if (null == _statistics)
{
_statistics = new SqlStatistics();
}
else
{
_statistics.ContinueOnNewConnection();
}
}
SqlStatistics statistics = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
statistics = SqlStatistics.StartTimer(Statistics);
System.Transactions.Transaction transaction = ADP.GetCurrentTransaction();
TaskCompletionSource<DbConnectionInternal> completion = new TaskCompletionSource<DbConnectionInternal>(transaction);
TaskCompletionSource<object> result = new TaskCompletionSource<object>();
if (cancellationToken.IsCancellationRequested)
{
result.SetCanceled();
return result.Task;
}
if (IsContextConnection)
{
result.SetException(ADP.ExceptionWithStackTrace(SQL.NotAvailableOnContextConnection()));
return result.Task;
}
bool completed;
try
{
completed = TryOpen(completion);
}
catch (Exception e)
{
result.SetException(e);
return result.Task;
}
if (completed)
{
result.SetResult(null);
}
else
{
CancellationTokenRegistration registration = new CancellationTokenRegistration();
if (cancellationToken.CanBeCanceled)
{
registration = cancellationToken.Register(() => completion.TrySetCanceled());
}
OpenAsyncRetry retry = new OpenAsyncRetry(this, completion, result, registration);
_currentCompletion = new Tuple<TaskCompletionSource<DbConnectionInternal>, Task>(completion, result.Task);
completion.Task.ContinueWith(retry.Retry, TaskScheduler.Default);
return result.Task;
}
return result.Task;
}
finally
{
SqlStatistics.StopTimer(statistics);
}
}
finally
{
Bid.ScopeLeave(ref hscp);
}
}
public void ResetStatistics()
{
if (IsContextConnection)
{
throw SQL.NotAvailableOnContextConnection();
}
if (null != Statistics)
{
Statistics.Reset();
if (ConnectionState.Open == State)
{
ADP.TimerCurrent(out _statistics._openTimestamp);
}
}
}
public IDictionary RetrieveStatistics()
{
if (IsContextConnection)
{
throw SQL.NotAvailableOnContextConnection();
}
if (null != Statistics)
{
UpdateStatistics();
return Statistics.GetHashtable();
}
else
{
return new SqlStatistics().GetHashtable();
}
}
}