public async Task SaveAsync()
        {
            if (!_connection.IsValueCreated)
            {
                return;
            }

            try
            {
                await _transaction.CommitAsync();
            }
            catch (Exception e)
            {
                await _transaction.RollbackAsync();

                throw new Exception("Failed to commit changes to database", e);
            }
            finally
            {
                await _transaction.DisposeAsync();

                _transaction = (SqliteTransaction)await _connection.Value.BeginTransactionAsync();
            }
        }
Example #2
0
        protected async Task ReadAsync <T>(DbContext context, Type type, IList <T> entities, TableInfo tableInfo, Action <decimal> progress, CancellationToken cancellationToken, bool isAsync) where T : class
        {
            SqliteConnection connection = isAsync ? await OpenAndGetSqliteConnectionAsync(context, tableInfo.BulkConfig, cancellationToken).ConfigureAwait(false)
                                                        : OpenAndGetSqliteConnection(context, tableInfo.BulkConfig);

            bool doExplicitCommit         = false;
            SqliteTransaction transaction = null;

            try
            {
                if (context.Database.CurrentTransaction == null)
                {
                    //context.Database.UseTransaction(connection.BeginTransaction());
                    doExplicitCommit = true;
                }

                transaction = doExplicitCommit ? connection.BeginTransaction()
                                               : (SqliteTransaction)context.Database.CurrentTransaction.GetUnderlyingTransaction(tableInfo.BulkConfig);

                SqliteCommand command = connection.CreateCommand();
                command.Transaction = transaction;

                // CREATE
                command.CommandText = SqlQueryBuilderSqlite.CreateTableCopy(tableInfo.FullTableName, tableInfo.FullTempTableName);
                if (isAsync)
                {
                    await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    command.ExecuteNonQuery();
                }

                tableInfo.BulkConfig.OperationType = OperationType.Insert;
                tableInfo.InsertToTempTable        = true;
                tableInfo.SqliteConnection         = connection;
                tableInfo.SqliteTransaction        = transaction;
                // INSERT
                if (isAsync)
                {
                    await InsertAsync(context, type, entities, tableInfo, progress, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    InsertAsync(context, type, entities, tableInfo, progress, cancellationToken, isAsync: false).GetAwaiter().GetResult();
                }

                // JOIN
                List <T> existingEntities;
                var      sqlSelectJoinTable = SqlQueryBuilder.SelectJoinTable(tableInfo);
                Expression <Func <DbContext, IQueryable <T> > > expression = tableInfo.GetQueryExpression <T>(sqlSelectJoinTable, false);
                var compiled = EF.CompileQuery(expression); // instead using Compiled queries
                existingEntities = compiled(context).ToList();

                tableInfo.UpdateReadEntities(type, entities, existingEntities);

                // DROP
                command.CommandText = SqlQueryBuilderSqlite.DropTable(tableInfo.FullTempTableName);
                if (isAsync)
                {
                    await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    command.ExecuteNonQuery();
                }

                if (doExplicitCommit)
                {
                    transaction.Commit();
                }
            }
            finally
            {
                if (doExplicitCommit)
                {
                    if (isAsync)
                    {
                        await transaction.DisposeAsync();

                        await context.Database.CloseConnectionAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        transaction.Dispose();
                        context.Database.CloseConnection();
                    }
                }
            }
        }