PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/System.Data.SqlClient/tests/ManualTests/SQL/TransactionTest/TransactionTest.cs

https://gitlab.com/0072016/0072016-corefx-
C# | 369 lines | 293 code | 71 blank | 5 comment | 6 complexity | 0dcbf40570371a7bd6cd8644604540e4 MD5 | raw file
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using Xunit;
  5. namespace System.Data.SqlClient.ManualTesting.Tests
  6. {
  7. public class TransactionTest
  8. {
  9. [Fact]
  10. public void TestYukon()
  11. {
  12. new TransactionTestWorker(DataTestClass.SQL2005_Northwind + ";multipleactiveresultsets=true;").StartTest();
  13. }
  14. [Fact]
  15. public void TestKatmai()
  16. {
  17. new TransactionTestWorker(DataTestClass.SQL2008_Northwind + ";multipleactiveresultsets=true;").StartTest();
  18. }
  19. }
  20. internal class TransactionTestWorker
  21. {
  22. private static string s_tempTableName1 = string.Format("TEST_{0}{1}{2}", Environment.GetEnvironmentVariable("ComputerName"), Environment.TickCount, Guid.NewGuid()).Replace('-', '_');
  23. private static string s_tempTableName2 = s_tempTableName1 + "_2";
  24. private string _connectionString;
  25. public TransactionTestWorker(string connectionString)
  26. {
  27. _connectionString = connectionString;
  28. }
  29. public void StartTest()
  30. {
  31. try
  32. {
  33. PrepareTables();
  34. CommitTransactionTest();
  35. ResetTables();
  36. RollbackTransactionTest();
  37. ResetTables();
  38. ScopedTransactionTest();
  39. ResetTables();
  40. ExceptionTest();
  41. ResetTables();
  42. ReadUncommitedIsolationLevel_ShouldReturnUncommitedData();
  43. ResetTables();
  44. ReadCommitedIsolationLevel_ShouldReceiveTimeoutExceptionBecauseItWaitsForUncommitedTransaction();
  45. ResetTables();
  46. }
  47. finally
  48. {
  49. //make sure to clean up
  50. DropTempTables();
  51. }
  52. }
  53. private void PrepareTables()
  54. {
  55. using (var conn = new SqlConnection(_connectionString))
  56. {
  57. conn.Open();
  58. SqlCommand command = new SqlCommand(string.Format("CREATE TABLE [{0}]([CustomerID] [nchar](5) NOT NULL PRIMARY KEY, [CompanyName] [nvarchar](40) NOT NULL, [ContactName] [nvarchar](30) NULL)", s_tempTableName1), conn);
  59. command.ExecuteNonQuery();
  60. command.CommandText = "create table " + s_tempTableName2 + "(col1 int, col2 varchar(32))";
  61. command.ExecuteNonQuery();
  62. }
  63. }
  64. private void DropTempTables()
  65. {
  66. using (var conn = new SqlConnection(_connectionString))
  67. {
  68. SqlCommand command = new SqlCommand(
  69. string.Format("DROP TABLE [{0}]; DROP TABLE [{1}]", s_tempTableName1, s_tempTableName2), conn);
  70. conn.Open();
  71. command.ExecuteNonQuery();
  72. }
  73. }
  74. public void ResetTables()
  75. {
  76. using (SqlConnection connection = new SqlConnection(_connectionString))
  77. {
  78. connection.Open();
  79. using (SqlCommand command = new SqlCommand(string.Format("TRUNCATE TABLE [{0}]; TRUNCATE TABLE [{1}]", s_tempTableName1, s_tempTableName2), connection))
  80. {
  81. command.ExecuteNonQuery();
  82. }
  83. }
  84. }
  85. private void CommitTransactionTest()
  86. {
  87. using (SqlConnection connection = new SqlConnection(_connectionString))
  88. {
  89. SqlCommand command = new SqlCommand("select * from " + s_tempTableName1 + " where CustomerID='ZYXWV'", connection);
  90. connection.Open();
  91. SqlTransaction tx = connection.BeginTransaction();
  92. command.Transaction = tx;
  93. using (SqlDataReader reader = command.ExecuteReader())
  94. {
  95. Assert.False(reader.HasRows, "Error: table is in incorrect state for test.");
  96. }
  97. using (SqlCommand command2 = connection.CreateCommand())
  98. {
  99. command2.Transaction = tx;
  100. command2.CommandText = "INSERT INTO " + s_tempTableName1 + " VALUES ( 'ZYXWV', 'XYZ', 'John' );";
  101. command2.ExecuteNonQuery();
  102. }
  103. tx.Commit();
  104. using (SqlDataReader reader = command.ExecuteReader())
  105. {
  106. int count = 0;
  107. while (reader.Read()) { count++; }
  108. Assert.True(count == 1, "Error: incorrect number of rows in table after update.");
  109. Assert.Equal(count, 1);
  110. }
  111. }
  112. }
  113. private void RollbackTransactionTest()
  114. {
  115. using (SqlConnection connection = new SqlConnection(_connectionString))
  116. {
  117. SqlCommand command = new SqlCommand("select * from " + s_tempTableName1 + " where CustomerID='ZYXWV'",
  118. connection);
  119. connection.Open();
  120. SqlTransaction tx = connection.BeginTransaction();
  121. command.Transaction = tx;
  122. using (SqlDataReader reader = command.ExecuteReader())
  123. {
  124. Assert.False(reader.HasRows, "Error: table is in incorrect state for test.");
  125. }
  126. using (SqlCommand command2 = connection.CreateCommand())
  127. {
  128. command2.Transaction = tx;
  129. command2.CommandText = "INSERT INTO " + s_tempTableName1 + " VALUES ( 'ZYXWV', 'XYZ', 'John' );";
  130. command2.ExecuteNonQuery();
  131. }
  132. tx.Rollback();
  133. using (SqlDataReader reader = command.ExecuteReader())
  134. {
  135. Assert.False(reader.HasRows, "Error Rollback Test : incorrect number of rows in table after rollback.");
  136. int count = 0;
  137. while (reader.Read()) count++;
  138. Assert.Equal(count, 0);
  139. }
  140. connection.Close();
  141. }
  142. }
  143. private void ScopedTransactionTest()
  144. {
  145. using (SqlConnection connection = new SqlConnection(_connectionString))
  146. {
  147. SqlCommand command = new SqlCommand("select * from " + s_tempTableName1 + " where CustomerID='ZYXWV'",
  148. connection);
  149. connection.Open();
  150. SqlTransaction tx = connection.BeginTransaction("transName");
  151. command.Transaction = tx;
  152. using (SqlDataReader reader = command.ExecuteReader())
  153. {
  154. Assert.False(reader.HasRows, "Error: table is in incorrect state for test.");
  155. }
  156. using (SqlCommand command2 = connection.CreateCommand())
  157. {
  158. command2.Transaction = tx;
  159. command2.CommandText = "INSERT INTO " + s_tempTableName1 + " VALUES ( 'ZYXWV', 'XYZ', 'John' );";
  160. command2.ExecuteNonQuery();
  161. }
  162. tx.Save("saveName");
  163. //insert another one
  164. using (SqlCommand command2 = connection.CreateCommand())
  165. {
  166. command2.Transaction = tx;
  167. command2.CommandText = "INSERT INTO " + s_tempTableName1 + " VALUES ( 'ZYXW2', 'XY2', 'KK' );";
  168. command2.ExecuteNonQuery();
  169. }
  170. tx.Rollback("saveName");
  171. using (SqlDataReader reader = command.ExecuteReader())
  172. {
  173. Assert.True(reader.HasRows, "Error Scoped Transaction Test : incorrect number of rows in table after rollback to save state one.");
  174. int count = 0;
  175. while (reader.Read()) count++;
  176. Assert.Equal(count, 1);
  177. }
  178. tx.Rollback();
  179. connection.Close();
  180. }
  181. }
  182. private void ExceptionTest()
  183. {
  184. using (SqlConnection connection = new SqlConnection(_connectionString))
  185. {
  186. connection.Open();
  187. SqlTransaction tx = connection.BeginTransaction();
  188. string invalidSaveStateMessage = SystemDataResourceManager.Instance.SQL_NullEmptyTransactionName;
  189. string executeCommandWithoutTransactionMessage = SystemDataResourceManager.Instance.ADP_TransactionRequired("ExecuteNonQuery");
  190. string transactionConflictErrorMessage = SystemDataResourceManager.Instance.ADP_TransactionConnectionMismatch;
  191. string parallelTransactionErrorMessage = SystemDataResourceManager.Instance.ADP_ParallelTransactionsNotSupported("SqlConnection");
  192. AssertException<InvalidOperationException>(() =>
  193. {
  194. SqlCommand command = new SqlCommand("sql", connection);
  195. command.ExecuteNonQuery();
  196. }, executeCommandWithoutTransactionMessage);
  197. AssertException<InvalidOperationException>(() =>
  198. {
  199. SqlConnection con1 = new SqlConnection(_connectionString);
  200. con1.Open();
  201. SqlCommand command = new SqlCommand("sql", con1);
  202. command.Transaction = tx;
  203. command.ExecuteNonQuery();
  204. }, transactionConflictErrorMessage);
  205. AssertException<InvalidOperationException>(() =>
  206. {
  207. connection.BeginTransaction(null);
  208. }, parallelTransactionErrorMessage);
  209. AssertException<InvalidOperationException>(() =>
  210. {
  211. connection.BeginTransaction("");
  212. }, parallelTransactionErrorMessage);
  213. AssertException<ArgumentException>(() =>
  214. {
  215. tx.Rollback(null);
  216. }, invalidSaveStateMessage);
  217. AssertException<ArgumentException>(() =>
  218. {
  219. tx.Rollback("");
  220. }, invalidSaveStateMessage);
  221. AssertException<ArgumentException>(() =>
  222. {
  223. tx.Save(null);
  224. }, invalidSaveStateMessage);
  225. AssertException<ArgumentException>(() =>
  226. {
  227. tx.Save("");
  228. }, invalidSaveStateMessage);
  229. }
  230. }
  231. public static void AssertException<T>(Action action, string expectedErrorMessage) where T : Exception
  232. {
  233. var exception = Assert.Throws<T>(action);
  234. Assert.Equal(exception.Message, expectedErrorMessage);
  235. }
  236. private void ReadUncommitedIsolationLevel_ShouldReturnUncommitedData()
  237. {
  238. using (SqlConnection connection1 = new SqlConnection(_connectionString))
  239. {
  240. connection1.Open();
  241. SqlTransaction tx1 = connection1.BeginTransaction();
  242. using (SqlCommand command1 = connection1.CreateCommand())
  243. {
  244. command1.Transaction = tx1;
  245. command1.CommandText = "INSERT INTO " + s_tempTableName1 + " VALUES ( 'ZYXWV', 'XYZ', 'John' );";
  246. command1.ExecuteNonQuery();
  247. }
  248. using (SqlConnection connection2 = new SqlConnection(_connectionString))
  249. {
  250. SqlCommand command2 =
  251. new SqlCommand("select * from " + s_tempTableName1 + " where CustomerID='ZYXWV'",
  252. connection2);
  253. connection2.Open();
  254. SqlTransaction tx2 = connection2.BeginTransaction(IsolationLevel.ReadUncommitted);
  255. command2.Transaction = tx2;
  256. using (SqlDataReader reader = command2.ExecuteReader())
  257. {
  258. int count = 0;
  259. while (reader.Read()) count++;
  260. Assert.True(count == 1, "Should Expected 1 row because Isolation Level is read uncommitted which should return uncommitted data.");
  261. }
  262. tx2.Rollback();
  263. connection2.Close();
  264. }
  265. tx1.Rollback();
  266. connection1.Close();
  267. }
  268. }
  269. private void ReadCommitedIsolationLevel_ShouldReceiveTimeoutExceptionBecauseItWaitsForUncommitedTransaction()
  270. {
  271. using (SqlConnection connection1 = new SqlConnection(_connectionString))
  272. {
  273. connection1.Open();
  274. SqlTransaction tx1 = connection1.BeginTransaction();
  275. using (SqlCommand command1 = connection1.CreateCommand())
  276. {
  277. command1.Transaction = tx1;
  278. command1.CommandText = "INSERT INTO " + s_tempTableName1 + " VALUES ( 'ZYXWV', 'XYZ', 'John' );";
  279. command1.ExecuteNonQuery();
  280. }
  281. using (SqlConnection connection2 = new SqlConnection(_connectionString))
  282. {
  283. SqlCommand command2 =
  284. new SqlCommand("select * from " + s_tempTableName1 + " where CustomerID='ZYXWV'",
  285. connection2);
  286. connection2.Open();
  287. SqlTransaction tx2 = connection2.BeginTransaction(IsolationLevel.ReadCommitted);
  288. command2.Transaction = tx2;
  289. AssertException<SqlException>(() => command2.ExecuteReader(), SystemDataResourceManager.Instance.SQL_Timeout as string);
  290. tx2.Rollback();
  291. connection2.Close();
  292. }
  293. tx1.Rollback();
  294. connection1.Close();
  295. }
  296. }
  297. }
  298. }