Skip to content

Commit

Permalink
SQLite: execute bulk operations within a transaction, otherwise SQLit…
Browse files Browse the repository at this point in the history
…e will start a new transaction for every statement
  • Loading branch information
PawelGerr committed Dec 4, 2024
1 parent 8eda61a commit 7d40a3d
Showing 1 changed file with 12 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public async Task<int> BulkUpdateAsync<T>(
options.PropertiesToUpdate.DeterminePropertiesForUpdate(entityType, null),
sqliteOptions.AutoIncrementBehavior);
var tableName = entityType.GetTableName()
?? throw new Exception($"The entity '{entityType.Name}' has no table name.");
?? throw new Exception($"The entity '{entityType.Name}' has no table name.");

return await ExecuteBulkOperationAsync(entities, entityType.GetSchema(), tableName, ctx, cancellationToken);
}
Expand All @@ -180,7 +180,7 @@ public async Task<int> BulkInsertOrUpdateAsync<T>(
sqliteOptions.PropertiesToUpdate.DeterminePropertiesForUpdate(entityType, true),
sqliteOptions.AutoIncrementBehavior);
var tableName = entityType.GetTableName()
?? throw new Exception($"The entity '{entityType.Name}' has no table name.");
?? throw new Exception($"The entity '{entityType.Name}' has no table name.");

return await ExecuteBulkOperationAsync(entities, entityType.GetSchema(), tableName, ctx, cancellationToken);
}
Expand All @@ -196,6 +196,11 @@ private async Task<int> ExecuteBulkOperationAsync<T>(

try
{
// Execute bulk operations within a transaction, otherwise SQLite will start a new transaction for every statement
await using var tx = _ctx.Database.CurrentTransaction == null
? await _ctx.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false)
: null;

var tableIdentifier = _sqlGenerationHelper.DelimitIdentifier(tableName, schema);

using var reader = bulkOperationContext.CreateReader(entitiesOrValues);
Expand All @@ -207,6 +212,9 @@ private async Task<int> ExecuteBulkOperationAsync<T>(
numberOfAffectedRows += await ExecuteBulkOperationForSeparatedOwnedEntitiesAsync((IReadOnlyList<object>)readEntities, bulkOperationContext, cancellationToken);
}

if (tx is not null)
await tx.CommitAsync(cancellationToken);

return numberOfAffectedRows;
}
finally
Expand All @@ -228,7 +236,7 @@ private async Task<int> ExecuteBulkOperationForSeparatedOwnedEntitiesAsync(
foreach (var childContext in parentBulkOperationContext.GetChildren(parentEntities))
{
var childTableName = childContext.EntityType.GetTableName()
?? throw new InvalidOperationException($"The entity '{childContext.EntityType.Name}' has no table name.");
?? throw new InvalidOperationException($"The entity '{childContext.EntityType.Name}' has no table name.");

numberOfAffectedRows += await ExecuteBulkOperationAsync(childContext.Entities,
childContext.EntityType.GetSchema(),
Expand Down Expand Up @@ -416,7 +424,7 @@ public async Task TruncateTableAsync(Type type, CancellationToken cancellationTo
{
var entityType = _ctx.Model.GetEntityType(type);
var tableName = entityType.GetTableName()
?? throw new InvalidOperationException($"The entity '{entityType.Name}' has no table name.");
?? throw new InvalidOperationException($"The entity '{entityType.Name}' has no table name.");

var tableIdentifier = _sqlGenerationHelper.DelimitIdentifier(tableName, entityType.GetSchema());
var truncateStatement = $"DELETE FROM {tableIdentifier};";
Expand Down

0 comments on commit 7d40a3d

Please sign in to comment.