using System; using System.Data.OleDb; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace EntityFrameworkCore.Jet.Data.Tests { [TestClass] [DoNotParallelize] public class ConnectionPoolingTest { private const string StoreName = nameof(ConnectionPoolingTest) + ".accdb"; private const string DummyStoreName = nameof(ConnectionPoolingTest) + "Dummy.accdb"; [TestInitialize] public void Setup() { using (var connection = Helpers.CreateAndOpenDatabase(StoreName)) { using var command = connection.CreateCommand("CREATE TABLE SimpleTable ( Col varchar(10) )"); command.ExecuteNonQuery(); } JetConnection.ClearAllPools(); } [TestCleanup] public void TearDown() { Helpers.DeleteDatabase(StoreName); } [TestMethod] public void Open_Connection_Without_Connection_String() { using var connection = new JetConnection(); Assert.Throws(() => connection.Open()); } [TestMethod] public void ExecuteReader_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory), Helpers.DataAccessProviderFactory); using var command = connection.CreateCommand($"select * from `{JetConnection.DefaultDualTableName}`"); var ex = Assert.Throws(() => command.ExecuteReader()); Assert.AreEqual("\"ExecuteReader\" requires a connection in Open state. Current connection state is Closed", ex.Message); } [TestMethod] public void ExecuteNonQuery_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory), Helpers.DataAccessProviderFactory); using var command = connection.CreateCommand($"select * from `{JetConnection.DefaultDualTableName}`"); var ex = Assert.Throws(() => command.ExecuteNonQuery()); Assert.AreEqual("\"ExecuteNonQuery\" requires a connection in Open state. Current connection state is Closed", ex.Message); } [TestMethod] public void ExecuteScalar_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory), Helpers.DataAccessProviderFactory); using var command = connection.CreateCommand($"select * from `{JetConnection.DefaultDualTableName}`"); var ex = Assert.Throws(() => command.ExecuteScalar()); Assert.AreEqual("\"ExecuteScalar\" requires a connection in Open state. Current connection state is Closed", ex.Message); } [TestMethod] public void Prepare_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory), Helpers.DataAccessProviderFactory); using var command = connection.CreateCommand($"select * from `{JetConnection.DefaultDualTableName}`"); var ex = Assert.Throws(() => command.Prepare()); Assert.AreEqual("\"Prepare\" requires a connection in Open state. Current connection state is Closed", ex.Message); } [TestMethod] public void GetDataReader_From_Open_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory), Helpers.DataAccessProviderFactory); connection.Open(); var dataReader = connection.CreateCommand($"select * from `{JetConnection.DefaultDualTableName}`") .ExecuteReader(); while (dataReader.Read()) { } } [TestMethod] public void GetTransaction_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); Assert.Throws(() => connection.BeginTransaction()); } [TestMethod] public void Change_Database_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); Assert.Throws(() => connection.ChangeDatabase("abcd")); } [TestMethod] public void Change_Database_From_Open_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); Assert.Throws(() => connection.ChangeDatabase("abcd")); } [TestMethod] public void Change_ConnectionString_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.ConnectionString = DummyStoreName; } [TestMethod] public void Change_ConnectionString_From_Open_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); Assert.Throws(() => connection.ConnectionString = DummyStoreName); } [TestMethod] public void Read_ConnectionString_From_Closed0_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); Assert.AreEqual(connectionString, connection.ConnectionString); } [TestMethod] public void Read_ConnectionString_From_Closed1_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); connection.Close(); Assert.AreEqual(connectionString, connection.ConnectionString); } [TestMethod] public void Read_ConnectionString_From_Open_Closed_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); connection.Open(); connection.Close(); Assert.AreEqual(connectionString, connection.ConnectionString); } [TestMethod] public void Read_ConnectionString_From_Disposed_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); connection.Dispose(); Assert.AreEqual(String.Empty, connection.ConnectionString); } [TestMethod] public void Read_ConnectionString_From_Open_Disposed_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); connection.Open(); connection.Dispose(); Assert.AreEqual(String.Empty, connection.ConnectionString); } [TestMethod] public void Read_ConnectionString_From_Open_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); connection.Open(); Assert.AreEqual(connectionString, connection.ConnectionString); } [TestMethod] public void Read_Database_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); Assert.AreEqual(string.Empty, connection.Database); } [TestMethod] public void Read_Database_From_Open_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); Assert.AreEqual(string.Empty, connection.Database); } [TestMethod] public void Read_ServerVersion_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); Assert.Throws(() => _ = connection.ServerVersion); } [TestMethod] public void Read_ServerVersion_From_Open_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); Console.WriteLine(connection.ServerVersion); } [TestMethod] public void Read_Database_From_Disposed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Dispose(); Assert.AreEqual(string.Empty, connection.Database); } [TestMethod] public void Read_DataSource_From_Closed_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); var dataAccessProviderType = JetConnection.GetDataAccessProviderType(connectionString); var dataAccessProviderFactory = JetFactory.GetDataAccessProviderFactory(dataAccessProviderType); var connectionStringBuilder = dataAccessProviderFactory.CreateConnectionStringBuilder(); connectionStringBuilder.ConnectionString = connectionString; var fileName = connectionStringBuilder.GetDataSource(); using var connection = new JetConnection(connectionString); Assert.AreEqual(fileName, connection.DataSource); } [TestMethod] public void Read_DataSource_From_Open_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); var dataAccessProviderType = JetConnection.GetDataAccessProviderType(connectionString); var dataAccessProviderFactory = JetFactory.GetDataAccessProviderFactory(dataAccessProviderType); var connectionStringBuilder = dataAccessProviderFactory.CreateConnectionStringBuilder(); connectionStringBuilder.ConnectionString = connectionString; var fileName = connectionStringBuilder.GetDataSource(); using var connection = new JetConnection(connectionString); connection.Open(); Assert.AreEqual(fileName, connection.DataSource); } [TestMethod] public void Read_DataSource_From_Disposed_Connection() { var connectionString = JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory); using var connection = new JetConnection(connectionString); connection.Dispose(); Assert.AreEqual(string.Empty, connection.DataSource); } [TestMethod] public void DisposeSeveralTimes() { var stateChangeCount = 0; using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.StateChange += (sender, args) => { Console.WriteLine($"{args.OriginalState} => {args.CurrentState}"); stateChangeCount++; }; connection.Open(); connection.Dispose(); connection.Dispose(); connection.Dispose(); Assert.AreEqual(2, stateChangeCount); } [TestMethod] public void DisposeWithoutOpen() { var stateChangeCount = 0; using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.StateChange += (sender, args) => { Console.WriteLine($"{args.OriginalState} => {args.CurrentState}"); stateChangeCount++; }; connection.Dispose(); Assert.AreEqual(0, stateChangeCount); } [TestMethod] public void Read_Connection_String_After_Dispose() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); Assert.IsFalse(string.IsNullOrEmpty(connection.ConnectionString)); connection.Dispose(); Assert.IsTrue(string.IsNullOrEmpty(connection.ConnectionString)); } [TestMethod] public void OpenSeveralTimes() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); Assert.Throws(() => connection.Open()); } [TestMethod] public void CloseSeveralTimes() { var stateChangeCount = 0; using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.StateChange += (sender, args) => { Console.WriteLine($"{args.OriginalState} => {args.CurrentState}"); stateChangeCount++; }; connection.Close(); connection.Close(); Assert.AreEqual(0, stateChangeCount); } [TestMethod] public void OpenCloseSeveralTimes() { var stateChangeCount = 0; using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.StateChange += (sender, args) => { Console.WriteLine($"{args.OriginalState} => {args.CurrentState}"); stateChangeCount++; }; connection.Open(); connection.Close(); connection.Close(); Assert.AreEqual(2, stateChangeCount); } [TestMethod] public void Raise_Events() { var stateChangeCount = 0; using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.StateChange += (sender, args) => { Console.WriteLine($"{args.OriginalState} => {args.CurrentState}"); stateChangeCount++; }; connection.Open(); using var command = connection.CreateCommand($"select * from `{JetConnection.DefaultDualTableName}`"); var dataReader = command.ExecuteReader(); while (dataReader.Read()) { } connection.Close(); connection.Open(); connection.Dispose(); Assert.AreEqual(4, stateChangeCount); } [TestMethod] public void GetSchema_From_Open_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); connection.GetSchema(); connection.Close(); } [TestMethod] public void GetSchema_From_Closed_Connection() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); Assert.Throws(() => connection.GetSchema()); } [TestMethod] public void Transaction_Execute_Close_Open_Execute() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction = connection.BeginTransaction(); using (var command = connection.CreateCommand($"select count(*) from `{JetConnection.DefaultDualTableName}`")) { command.Transaction = transaction; command.ExecuteScalar(); } connection.Close(); connection.Open(); using (var command = connection.CreateCommand($"select count(*) from `{JetConnection.DefaultDualTableName}`")) { command.ExecuteScalar(); } } [TestMethod] public void Transaction_Execute_Commit_Close_Open_Execute() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction = connection.BeginTransaction(); using (var command = connection.CreateCommand($"select count(*) from `{JetConnection.DefaultDualTableName}`")) { command.Transaction = transaction; command.ExecuteScalar(); } transaction.Commit(); connection.Close(); connection.Open(); using (var command = connection.CreateCommand($"select count(*) from `{JetConnection.DefaultDualTableName}`")) { command.ExecuteScalar(); } } [TestMethod] public void Transaction_Execute_Close_Open() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("INSERT INTO SimpleTable(Col) VALUES ('aaa')")) { command.Transaction = transaction; command.ExecuteScalar(); } connection.Close(); connection.Open(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { Assert.AreEqual(0, command.ExecuteScalar()); } } [TestMethod] public void Transaction_Execute_Close_Open_Commit() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("INSERT INTO SimpleTable(Col) VALUES ('aaa')")) { command.Transaction = transaction; command.ExecuteScalar(); } connection.Close(); JetConnection.ClearAllPools(); connection.Open(); Assert.Throws(() => transaction.Commit()); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { Assert.AreEqual(0, command.ExecuteScalar()); } } [TestMethod] public void Transaction_Execute_Close_Open_Transaction() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction1 = connection.BeginTransaction(); using (var command = connection.CreateCommand("INSERT INTO SimpleTable(Col) VALUES ('aaa')")) { command.Transaction = transaction1; command.ExecuteScalar(); } connection.Close(); connection.Open(); using var transaction2 = connection.BeginTransaction(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = transaction2; Assert.AreEqual(0, command.ExecuteScalar()); } } [TestMethod] public void Transaction_Transaction() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var firstTransaction = connection.BeginTransaction(); using var command = connection.CreateCommand("select count(*) from SimpleTable"); command.Transaction = firstTransaction; command.ExecuteScalar(); var ex = Assert.Throws(() => connection.BeginTransaction()); Assert.AreEqual("JetConnection does not support parallel transactions", ex.Message); } [TestMethod] public void Transaction_Commit_Transaction() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var firstTransaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = firstTransaction; command.ExecuteScalar(); } firstTransaction.Commit(); using var secondTransaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = secondTransaction; command.ExecuteScalar(); } connection.Close(); connection.Open(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.ExecuteScalar(); } } [TestMethod] public void Transaction_Rollback_Transaction() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var firstTransaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = firstTransaction; command.ExecuteScalar(); } firstTransaction.Rollback(); using var secondTransaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = secondTransaction; command.ExecuteScalar(); } connection.Close(); connection.Open(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.ExecuteScalar(); } } [TestMethod] public void Transaction_Execute_Commit_Execute_Transaction() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction = connection.BeginTransaction(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = transaction; command.ExecuteScalar(); } transaction.Commit(); using (var command = connection.CreateCommand("select count(*) from SimpleTable")) { command.Transaction = transaction; command.ExecuteScalar(); } Assert.Throws(() => transaction.Commit()); } [TestMethod] public void Transaction_Execute_Commit_Commit() { using var connection = new JetConnection(JetConnection.GetConnectionString(StoreName, Helpers.DataAccessProviderFactory)); connection.Open(); using var transaction = connection.BeginTransaction(); using var command = connection.CreateCommand("select count(*) from SimpleTable"); command.Transaction = transaction; command.ExecuteScalar(); transaction.Commit(); Assert.Throws(() => transaction.Commit()); } } }