public async Task AsyncDispose_actually_cleans_up() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); //Note: never use an async disposable like this. It might make a mess if the .ctor fails. For the test it's ok var unitOfWork = new UnitOfWork(sqliteDatabaseConnectionFactory); await using (unitOfWork) { await unitOfWork.OpenConnectionAsync() .ConfigureAwait(continueOnCapturedContext: false); await unitOfWork.BeginTransactionAsync() .ConfigureAwait(continueOnCapturedContext: false); //Pretending to forget to close/rollback Assert.That(unitOfWork.Connection, Is.Not.Null); Assert.That(unitOfWork.Transaction, Is.Not.Null); } Assert.That(unitOfWork.Connection, Is.Null); Assert.That(unitOfWork.Transaction, Is.Null); }
public void If_OptionsFactory_returns_null_default_options_are_used_as_fallback() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); UnitOfWorkOptionsProviderFunc optsFunc = () => null; using var unitOfWork = new SynchronousUnitOfWork(sqliteDatabaseConnectionFactory, optsFunc); Assert.That(unitOfWork.Options, Is.EqualTo(UnitOfWorkOptions.Default)); }
public void Transaction_can_t_be_rolled_back_without_beginning_it() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new SynchronousUnitOfWork(sqliteDatabaseConnectionFactory); void TryRollbackTransaction() { unitOfWork.RollbackTransaction(); } Assert.That(TryRollbackTransaction, Throws.InvalidOperationException); }
public void Closing_Connection_that_are_not_open_does_nothing() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new SynchronousUnitOfWork(sqliteDatabaseConnectionFactory); void TryCloseConnection() { unitOfWork.CloseConnection(); } Assert.DoesNotThrow(TryCloseConnection); }
public void Transaction_can_t_be_rolled_back_without_beginning_it() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new UnitOfWork(sqliteDatabaseConnectionFactory); async Task TryRollbackTransactionAsync() { await unitOfWork.RollbackTransactionAsync() .ConfigureAwait(false); } Assert.That(TryRollbackTransactionAsync, Throws.InvalidOperationException); }
public void Closing_Connection_that_are_not_open_does_nothing() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new UnitOfWork(sqliteDatabaseConnectionFactory); async Task TryCloseConnectionAsync() { await unitOfWork.CloseConnectionAsync() .ConfigureAwait(false); } Assert.That(TryCloseConnectionAsync, Throws.Nothing); }
public void Connection_can_t_be_closed_without_commiting_or_rolling_back_the_transaction() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new SynchronousUnitOfWork(sqliteDatabaseConnectionFactory); unitOfWork.BeginTransaction(); void TryCloseConnection() { unitOfWork.CloseConnection(); } Assert.That(TryCloseConnection, Throws.InvalidOperationException); }
public void A_Transaction_can_t_begin_twice() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new SynchronousUnitOfWork(sqliteDatabaseConnectionFactory); unitOfWork.BeginTransaction(); void BeginTransactionAgain() { unitOfWork.BeginTransaction(); } Assert.That(BeginTransactionAgain, Throws.InvalidOperationException); }
public async Task Connection_can_t_be_closed_without_commiting_or_rolling_back_the_transaction() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new UnitOfWork(sqliteDatabaseConnectionFactory); await unitOfWork.BeginTransactionAsync() .ConfigureAwait(false); async Task TryCloseConnectionAsync() { await unitOfWork.CloseConnectionAsync() .ConfigureAwait(false); } Assert.That(TryCloseConnectionAsync, Throws.InvalidOperationException); }
public async Task A_Transaction_can_t_begin_twice() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); using var unitOfWork = new UnitOfWork(sqliteDatabaseConnectionFactory); await unitOfWork.BeginTransactionAsync() .ConfigureAwait(false); async Task BeginTransactionAgainAsync() { await unitOfWork.BeginTransactionAsync() .ConfigureAwait(false); } Assert.That(BeginTransactionAgainAsync, Throws.InvalidOperationException); }
/// <summary> /// Add SQLite specific types for the Unit of Work /// </summary> public static IServiceCollection ForSQLite(this UnitOfWorkServiceBuilder builder, string connectionString) { if (builder is null) { throw new ArgumentNullException(nameof(builder)); } if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentException($"'{nameof(connectionString)}' cannot be null or empty", nameof(connectionString)); } var sqlConnectionString = new SQLiteDatabaseConnectionString(connectionString); builder.ServiceCollection.AddSingleton(sqlConnectionString); builder.ServiceCollection.AddTransient <IDatabaseConnectionFactory, SQLiteDatabaseConnectionFactory>(); return(builder.ServiceCollection); }
public void Multiple_connections_errors_are_ignored_when_the_appropriate_option_is_specified() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); var options = new UnitOfWorkOptions { ThrowOnMultipleTransactionsAttempts = true, ThrowOnMultipleConnectionsAttempts = false }; using var unitOfWork = new SynchronousUnitOfWork(sqliteDatabaseConnectionFactory, options); unitOfWork.OpenConnection(); void OpenConnectionAgain() { unitOfWork.OpenConnection(); } Assert.DoesNotThrow(OpenConnectionAgain); }
public async Task Multiple_connections_errors_are_ignored_when_the_appropriate_option_is_specified() { var sqliteDatabaseConnectionString = new SQLiteDatabaseConnectionString("Data Source = whatever.db"); var sqliteDatabaseConnectionFactory = new SQLiteDatabaseConnectionFactory(sqliteDatabaseConnectionString); var options = new UnitOfWorkOptions { ThrowOnMultipleTransactionsAttempts = true, ThrowOnMultipleConnectionsAttempts = false }; await using var unitOfWork = new UnitOfWork(sqliteDatabaseConnectionFactory, options); await unitOfWork.OpenConnectionAsync() .ConfigureAwait(continueOnCapturedContext: false); async Task OpenConnectionAgainAsync() { await unitOfWork.OpenConnectionAsync() .ConfigureAwait(continueOnCapturedContext: false); } Assert.DoesNotThrowAsync(OpenConnectionAgainAsync); }
public SQLiteDatabaseConnectionFactory(SQLiteDatabaseConnectionString connectionString) { this.connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString)); }