private static void TestMARSSessionPooling(string caseName, string connectionString, CommandType commandType, ExecuteType executeType, ReaderTestType readerTestType, GCType gcType) { SqlCommand[] cmd = new SqlCommand[CONCURRENT_COMMANDS]; SqlDataReader[] gch = new SqlDataReader[CONCURRENT_COMMANDS]; using (SqlConnection con = new SqlConnection(connectionString)) { con.Open(); for (int i = 0; i < CONCURRENT_COMMANDS; i++) { // Prepare all commands cmd[i] = con.CreateCommand(); switch (commandType) { case CommandType.Text: cmd[i].CommandText = _COMMAND_SQL; cmd[i].CommandTimeout = 120; break; case CommandType.StoredProcedure: cmd[i].CommandText = _COMMAND_RPC; cmd[i].CommandTimeout = 120; cmd[i].CommandType = CommandType.StoredProcedure; break; } } for (int i = 0; i < CONCURRENT_COMMANDS; i++) { switch (executeType) { case ExecuteType.ExecuteScalar: cmd[i].ExecuteScalar(); break; case ExecuteType.ExecuteNonQuery: cmd[i].ExecuteNonQuery(); break; case ExecuteType.ExecuteReader: if (readerTestType != ReaderTestType.ReaderGC) { gch[i] = cmd[i].ExecuteReader(); } switch (readerTestType) { case ReaderTestType.ReaderClose: { gch[i].Dispose(); break; } case ReaderTestType.ReaderDispose: gch[i].Dispose(); break; case ReaderTestType.ReaderGC: gch[i] = null; WeakReference weak = OpenReaderThenNullify(cmd[i]); GC.Collect(); if (gcType == GCType.Wait) { GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Error - target still alive!"); } break; case ReaderTestType.ConnectionClose: GC.SuppressFinalize(gch[i]); con.Close(); con.Open(); break; case ReaderTestType.NoCloses: GC.SuppressFinalize(gch[i]); break; } break; } if (readerTestType != ReaderTestType.NoCloses) { con.Close(); con.Open(); // Close and open, to re-assure collection! } using (SqlCommand verificationCmd = con.CreateCommand()) { verificationCmd.CommandText = COMMAND_STATUS; using (SqlDataReader rdr = verificationCmd.ExecuteReader()) { rdr.Read(); int connections = (int)rdr.GetValue(0); int spid1 = (Int16)rdr.GetValue(1); rdr.NextResult(); rdr.Read(); int requests = (int)rdr.GetValue(0); int spid2 = (Int16)rdr.GetValue(1); switch (executeType) { case ExecuteType.ExecuteScalar: case ExecuteType.ExecuteNonQuery: // 1 for connection, 1 for command Assert.True(connections == 2, "Failure - incorrect number of connections for ExecuteScalar! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ExecuteScalar! #requests: " + requests); break; case ExecuteType.ExecuteReader: switch (readerTestType) { case ReaderTestType.ReaderClose: case ReaderTestType.ReaderDispose: case ReaderTestType.ConnectionClose: // 1 for connection, 1 for command Assert.True(connections == 2, "Failure - Incorrect number of connections for ReaderClose / ReaderDispose / ConnectionClose! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ReaderClose/ReaderDispose/ConnectionClose! #requests: " + requests); break; case ReaderTestType.ReaderGC: switch (gcType) { case GCType.Wait: // 1 for connection, 1 for open reader Assert.True(connections == 2, "Failure - incorrect number of connections for ReaderGCWait! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ReaderGCWait! #requests: " + requests); break; case GCType.NoWait: // 1 for connection, 1 for open reader Assert.True(connections == 2, "Failure - incorrect number of connections for ReaderGCNoWait! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ReaderGCNoWait! #requests: " + requests); break; } break; case ReaderTestType.NoCloses: // 1 for connection, 1 for current command, 1 for 0 based array offset, plus i for open readers Assert.True(connections == (3 + i), "Failure - incorrect number of connections for NoCloses: " + connections + "\ni: " + i + " :::: requests: " + requests + " :::: spid1: " + spid1 + " ::::: spid2: " + spid2); // 1 for current command, 1 for 0 based array offset, plus i open readers Assert.True(requests == (2 + i), "Failure - incorrect number of requests for NoCloses: " + requests + "\ni: " + i + " :::: connections: " + connections + " :::: spid1: " + spid1 + " ::::: spid2: " + spid2); break; } break; } } } } } }
private static void TestReaderNonMarsCase(string caseName, string connectionString, ReaderTestType testType, ReaderVerificationType verificationType) { WeakReference weak = null; using (SqlConnection con = new SqlConnection(connectionString)) { con.Open(); using (SqlCommand cmd = con.CreateCommand()) { cmd.CommandText = COMMAND_TEXT_1; SqlDataReader gch = null; if ((testType != ReaderTestType.ReaderGC) && (testType != ReaderTestType.ReaderGCConnectionClose)) { gch = cmd.ExecuteReader(); } switch (testType) { case ReaderTestType.ReaderClose: gch.Dispose(); break; case ReaderTestType.ReaderDispose: gch.Dispose(); break; case ReaderTestType.ReaderGC: weak = OpenNullifyReader(cmd); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Reader is still alive!"); break; case ReaderTestType.ConnectionClose: GC.SuppressFinalize(gch); con.Close(); con.Open(); break; case ReaderTestType.ReaderGCConnectionClose: weak = OpenNullifyReader(cmd); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Reader is still alive!"); con.Close(); con.Open(); break; } switch (verificationType) { case ReaderVerificationType.ExecuteReader: cmd.CommandText = COMMAND_TEXT_2; using (SqlDataReader rdr = cmd.ExecuteReader()) { rdr.Read(); Assert.Equal(rdr.FieldCount, 1); Assert.Equal(rdr.GetName(0), COLUMN_NAME_2); } break; case ReaderVerificationType.ChangeDatabase: con.ChangeDatabase(CHANGE_DATABASE_NAME); Assert.Equal(con.Database, CHANGE_DATABASE_NAME); break; case ReaderVerificationType.BeginTransaction: cmd.Transaction = con.BeginTransaction(); cmd.CommandText = "select @@trancount"; int tranCount = (int)cmd.ExecuteScalar(); Assert.Equal(tranCount, 1); break; } } } }
private static void TestReaderMarsCase(string caseName, string connectionString, ReaderTestType testType, ReaderVerificationType verificationType) { WeakReference weak = null; SqlCommand[] cmd = new SqlCommand[CONCURRENT_COMMANDS]; SqlDataReader[] gch = new SqlDataReader[CONCURRENT_COMMANDS]; using (SqlConnection con = new SqlConnection(connectionString)) { con.Open(); for (int i = 0; i < CONCURRENT_COMMANDS; i++) { cmd[i] = con.CreateCommand(); cmd[i].CommandText = COMMAND_TEXT_1; if ((testType != ReaderTestType.ReaderGC) && (testType != ReaderTestType.ReaderGCConnectionClose)) { gch[i] = cmd[i].ExecuteReader(); } else { gch[i] = null; } } for (int i = 0; i < CONCURRENT_COMMANDS; i++) { switch (testType) { case ReaderTestType.ReaderClose: gch[i].Dispose(); break; case ReaderTestType.ReaderDispose: gch[i].Dispose(); break; case ReaderTestType.ReaderGC: weak = OpenNullifyReader(cmd[i]); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Transaction is still alive on TestReaderMars: ReaderGC"); break; case ReaderTestType.ConnectionClose: GC.SuppressFinalize(gch[i]); con.Close(); con.Open(); break; case ReaderTestType.ReaderGCConnectionClose: weak = OpenNullifyReader(cmd[i]); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Transaction is still alive on TestReaderMars: ReaderGCConnectionClose"); con.Close(); con.Open(); break; } cmd[i].Dispose(); } SqlCommand verificationCmd = con.CreateCommand(); switch (verificationType) { case ReaderVerificationType.ExecuteReader: verificationCmd.CommandText = COMMAND_TEXT_2; using (SqlDataReader rdr = verificationCmd.ExecuteReader()) { rdr.Read(); DataTestClass.AssertEqualsWithDescription(1, rdr.FieldCount, "Execute Reader should return expected Field count"); DataTestClass.AssertEqualsWithDescription(COLUMN_NAME_2, rdr.GetName(0), "Execute Reader should return expected Field name"); } break; case ReaderVerificationType.ChangeDatabase: con.ChangeDatabase(DATABASE_NAME); DataTestClass.AssertEqualsWithDescription(DATABASE_NAME, con.Database, "Change Database should return expected Database Name"); break; case ReaderVerificationType.BeginTransaction: verificationCmd.Transaction = con.BeginTransaction(); verificationCmd.CommandText = "select @@trancount"; int tranCount = (int)verificationCmd.ExecuteScalar(); DataTestClass.AssertEqualsWithDescription(1, tranCount, "Begin Transaction should return expected Transaction count"); break; } verificationCmd.Dispose(); } }
private static void TestMARSSessionPooling(string caseName, string connectionString, CommandType commandType, ExecuteType executeType, ReaderTestType readerTestType, GCType gcType) { SqlCommand[] cmd = new SqlCommand[CONCURRENT_COMMANDS]; SqlDataReader[] gch = new SqlDataReader[CONCURRENT_COMMANDS]; using (SqlConnection con = new SqlConnection(connectionString)) { con.Open(); for (int i = 0; i < CONCURRENT_COMMANDS; i++) { // Prepare all commands cmd[i] = con.CreateCommand(); switch (commandType) { case CommandType.Text: cmd[i].CommandText = _COMMAND_SQL; cmd[i].CommandTimeout = 120; break; case CommandType.StoredProcedure: cmd[i].CommandText = _COMMAND_RPC; cmd[i].CommandTimeout = 120; cmd[i].CommandType = CommandType.StoredProcedure; break; } } for (int i = 0; i < CONCURRENT_COMMANDS; i++) { switch (executeType) { case ExecuteType.ExecuteScalar: cmd[i].ExecuteScalar(); break; case ExecuteType.ExecuteNonQuery: cmd[i].ExecuteNonQuery(); break; case ExecuteType.ExecuteReader: if (readerTestType != ReaderTestType.ReaderGC) gch[i] = cmd[i].ExecuteReader(); switch (readerTestType) { case ReaderTestType.ReaderClose: { gch[i].Dispose(); break; } case ReaderTestType.ReaderDispose: gch[i].Dispose(); break; case ReaderTestType.ReaderGC: gch[i] = null; WeakReference weak = OpenReaderThenNullify(cmd[i]); GC.Collect(); if (gcType == GCType.Wait) { GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Error - target still alive!"); } break; case ReaderTestType.ConnectionClose: GC.SuppressFinalize(gch[i]); con.Close(); con.Open(); break; case ReaderTestType.NoCloses: GC.SuppressFinalize(gch[i]); break; } break; } if (readerTestType != ReaderTestType.NoCloses) { con.Close(); con.Open(); // Close and open, to re-assure collection! } SqlCommand verificationCmd = con.CreateCommand(); verificationCmd.CommandText = COMMAND_STATUS; using (SqlDataReader rdr = verificationCmd.ExecuteReader()) { rdr.Read(); int connections = (int)rdr.GetValue(0); rdr.NextResult(); rdr.Read(); int requests = (int)rdr.GetValue(0); switch (executeType) { case ExecuteType.ExecuteScalar: case ExecuteType.ExecuteNonQuery: // 1 for connection, 1 for command Assert.True(connections == 2, "Failure - incorrect number of connections for ExecuteScalar! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ExecuteScalar! #requests: " + requests); break; case ExecuteType.ExecuteReader: switch (readerTestType) { case ReaderTestType.ReaderClose: case ReaderTestType.ReaderDispose: case ReaderTestType.ConnectionClose: // 1 for connection, 1 for command Assert.True(connections == 2, "Failure - Incorrect number of connections for ReaderClose / ReaderDispose / ConnectionClose! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ReaderClose/ReaderDispose/ConnectionClose! #requests: " + requests); break; case ReaderTestType.ReaderGC: switch (gcType) { case GCType.Wait: // 1 for connection, 1 for open reader Assert.True(connections == 2, "Failure - incorrect number of connections for ReaderGCWait! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ReaderGCWait! #requests: " + requests); break; case GCType.NoWait: // 1 for connection, 1 for open reader Assert.True(connections == 2, "Failure - incorrect number of connections for ReaderGCNoWait! #connections: " + connections); // only 1 executing Assert.True(requests == 1, "Failure - incorrect number of requests for ReaderGCNoWait! #requests: " + requests); break; } break; case ReaderTestType.NoCloses: // 1 for connection, 1 for current command, 1 for 0 based array offset, plus i for open readers Assert.True(connections == (3 + i), "Failure - incorrect number of connections for NoCloses: " + connections); // 1 for current command, 1 for 0 based array offset, plus i open readers Assert.True(requests == (2 + i), "Failure - incorrect number of requests for NoCloses: " + requests); break; } break; } } } } }
private static void TestReaderNonMarsCase(string caseName, string connectionString, ReaderTestType testType, ReaderVerificationType verificationType) { WeakReference weak = null; using (SqlConnection con = new SqlConnection(connectionString)) { con.Open(); using (SqlCommand cmd = con.CreateCommand()) { cmd.CommandText = COMMAND_TEXT_1; SqlDataReader gch = null; if ((testType != ReaderTestType.ReaderGC) && (testType != ReaderTestType.ReaderGCConnectionClose)) gch = cmd.ExecuteReader(); switch (testType) { case ReaderTestType.ReaderClose: gch.Dispose(); break; case ReaderTestType.ReaderDispose: gch.Dispose(); break; case ReaderTestType.ReaderGC: weak = OpenNullifyReader(cmd); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Reader is still alive!"); break; case ReaderTestType.ConnectionClose: GC.SuppressFinalize(gch); con.Close(); con.Open(); break; case ReaderTestType.ReaderGCConnectionClose: weak = OpenNullifyReader(cmd); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Reader is still alive!"); con.Close(); con.Open(); break; } switch (verificationType) { case ReaderVerificationType.ExecuteReader: cmd.CommandText = COMMAND_TEXT_2; using (SqlDataReader rdr = cmd.ExecuteReader()) { rdr.Read(); Assert.Equal(rdr.FieldCount, 1); Assert.Equal(rdr.GetName(0), COLUMN_NAME_2); } break; case ReaderVerificationType.ChangeDatabase: con.ChangeDatabase(DATABASE_NAME); Assert.Equal(con.Database, DATABASE_NAME); break; case ReaderVerificationType.BeginTransaction: cmd.Transaction = con.BeginTransaction(); cmd.CommandText = "select @@trancount"; int tranCount = (int)cmd.ExecuteScalar(); Assert.Equal(tranCount, 1); break; } } } }
private static void TestReaderMarsCase(string caseName, string connectionString, ReaderTestType testType, ReaderVerificationType verificationType) { WeakReference weak = null; SqlCommand[] cmd = new SqlCommand[CONCURRENT_COMMANDS]; SqlDataReader[] gch = new SqlDataReader[CONCURRENT_COMMANDS]; using (SqlConnection con = new SqlConnection(connectionString)) { con.Open(); for (int i = 0; i < CONCURRENT_COMMANDS; i++) { cmd[i] = con.CreateCommand(); cmd[i].CommandText = COMMAND_TEXT_1; if ((testType != ReaderTestType.ReaderGC) && (testType != ReaderTestType.ReaderGCConnectionClose)) gch[i] = cmd[i].ExecuteReader(); else gch[i] = null; } for (int i = 0; i < CONCURRENT_COMMANDS; i++) { switch (testType) { case ReaderTestType.ReaderClose: gch[i].Dispose(); break; case ReaderTestType.ReaderDispose: gch[i].Dispose(); break; case ReaderTestType.ReaderGC: weak = OpenNullifyReader(cmd[i]); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Transaction is still alive on TestReaderMars: ReaderGC"); break; case ReaderTestType.ConnectionClose: GC.SuppressFinalize(gch[i]); con.Close(); con.Open(); break; case ReaderTestType.ReaderGCConnectionClose: weak = OpenNullifyReader(cmd[i]); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.False(weak.IsAlive, "Transaction is still alive on TestReaderMars: ReaderGCConnectionClose"); con.Close(); con.Open(); break; } cmd[i].Dispose(); } SqlCommand verificationCmd = con.CreateCommand(); switch (verificationType) { case ReaderVerificationType.ExecuteReader: verificationCmd.CommandText = COMMAND_TEXT_2; using (SqlDataReader rdr = verificationCmd.ExecuteReader()) { rdr.Read(); DataTestClass.AssertEqualsWithDescription(1, rdr.FieldCount, "Execute Reader should return expected Field count"); DataTestClass.AssertEqualsWithDescription(COLUMN_NAME_2, rdr.GetName(0), "Execute Reader should return expected Field name"); } break; case ReaderVerificationType.ChangeDatabase: con.ChangeDatabase(DATABASE_NAME); DataTestClass.AssertEqualsWithDescription(DATABASE_NAME, con.Database, "Change Database should return expected Database Name"); break; case ReaderVerificationType.BeginTransaction: verificationCmd.Transaction = con.BeginTransaction(); verificationCmd.CommandText = "select @@trancount"; int tranCount = (int)verificationCmd.ExecuteScalar(); DataTestClass.AssertEqualsWithDescription(1, tranCount, "Begin Transaction should return expected Transaction count"); break; } verificationCmd.Dispose(); } }