Ejemplo n.º 1
0
        public void TestConnectionDoesNotLeak()
        {
            var applicationName  = nameof(TestConnectionDoesNotLeak) + Guid.NewGuid();
            var connectionString = new SqlConnectionStringBuilder(ConnectionStringProvider.ConnectionString)
            {
                ApplicationName = applicationName,
            }
            .ConnectionString;

            using (ConnectionStringProvider.UseConnectionString(connectionString))
                using (var engine = this.CreateEngine())
                {
                    var @lock = engine.CreateLock(nameof(TestConnectionDoesNotLeak));

                    for (var i = 0; i < 30; ++i)
                    {
                        using (@lock.Acquire())
                        {
                            CountActiveSessions().ShouldEqual(1, this.GetType().Name);
                        }
                        // still alive due to pooling
                        CountActiveSessions().ShouldEqual(1, this.GetType().Name);
                    }
                }

            using (var connection = SqlHelpers.CreateConnection(connectionString))
            {
                SqlTestHelper.ClearPool(connection);
                // checking immediately seems flaky; likely clear pool finishing
                // doesn't guarantee that SQL will immediately reflect the clear
                var maxWaitForPoolsToClear = TimeSpan.FromSeconds(5);
                var stopwatch = Stopwatch.StartNew();
                do
                {
                    var activeCount = CountActiveSessions();
                    if (activeCount == 0)
                    {
                        return;
                    }
                    Thread.Sleep(25);
                }while (stopwatch.Elapsed < maxWaitForPoolsToClear);
            }

            int CountActiveSessions()
            {
                using var connection = SqlHelpers.CreateConnection(ConnectionStringProvider.ConnectionString);
                connection.Open();
                using var command   = connection.CreateCommand();
                command.CommandText = $@"SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE program_name = '{applicationName}'";
                return((int)command.ExecuteScalar());
            }
        }
        public void TestIsolationLevelLeakage()
        {
            const string IsolationLevelQuery = @"
                SELECT CASE transaction_isolation_level 
                WHEN 0 THEN 'Unspecified' 
                WHEN 1 THEN 'ReadUncommitted' 
                WHEN 2 THEN 'ReadCommitted' 
                WHEN 3 THEN 'RepeatableRead' 
                WHEN 4 THEN 'Serializable' 
                WHEN 5 THEN 'Snapshot' END AS isolationLevel 
                FROM sys.dm_exec_sessions 
                WHERE session_id = @@SPID";

            var connectionString = new SqlConnectionStringBuilder(ConnectionStringProvider.ConnectionString)
            {
                ApplicationName = nameof(TestIsolationLevelLeakage),
                // makes it easy to test for leaks since all connections are the same
                MaxPoolSize = 1,
            }
            .ConnectionString;

            using (var connection = SqlHelpers.CreateConnection(connectionString)) { SqlTestHelper.ClearPool(connection); }

            using var engine = new TEngineFactory().Create <TransactionBasedConnectionStringProvider>();
            var @lock = engine.CreateLock(nameof(TestIsolationLevelLeakage));

            @lock.Acquire().Dispose();
            using (var connection = SqlHelpers.CreateConnection(connectionString))
            {
                connection.Open();
                using var command   = connection.CreateCommand();
                command.CommandText = IsolationLevelQuery;
                command.ExecuteScalar().ShouldEqual(IsolationLevel.ReadCommitted.ToString());
            }

            @lock.AcquireAsync().Result.Dispose();
            using (var connection = SqlHelpers.CreateConnection(connectionString))
            {
                connection.Open();
                using var command   = connection.CreateCommand();
                command.CommandText = IsolationLevelQuery;
                command.ExecuteScalar().ShouldEqual(IsolationLevel.ReadCommitted.ToString());
            }
        }