1
0

Added DbExtensions for database transactions

This commit is contained in:
2023-03-29 18:11:09 +02:00
parent f2d07dcf1f
commit 5c4165dfd0
3 changed files with 95 additions and 4 deletions

View File

@@ -0,0 +1,91 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Storage;
namespace Microsoft.EntityFrameworkCore
{
/// <summary>
/// Extensions for the <see cref="DbContext"/>.
/// </summary>
public static class DbContextExensions
{
/// <summary>
/// Starts a new transaction.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-transactions">Transactions in EF Core</see> for more information.
/// </remarks>
/// <param name="dbContext">The current <see cref="DbContext"/>.</param>
/// <returns>
/// A <see cref="IDbContextTransaction" /> that represents the started transaction.
/// </returns>
public static IDbContextTransaction BeginTransaction(this DbContext dbContext)
{
if (dbContext.Database.GetProviderType() == DatabaseFacadeExtensions.DatabaseProvider.InMemory)
return new DbContextTransactionStub();
return dbContext.Database.BeginTransaction();
}
/// <summary>
/// Asynchronously starts a new transaction.
/// </summary>
/// <remarks>
/// <para>
/// Entity Framework Core does not support multiple parallel operations being run on the same DbContext instance. This
/// includes both parallel execution of async queries and any explicit concurrent use from multiple threads.
/// Therefore, always await async calls immediately, or use separate DbContext instances for operations that execute
/// in parallel. See <see href="https://aka.ms/efcore-docs-threading">Avoiding DbContext threading issues</see>
/// for more information.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-transactions">Transactions in EF Core</see> for more information.
/// </para>
/// </remarks>
/// <param name="dbContext">The current <see cref="DbContext"/>.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>
/// A task that represents the asynchronous transaction initialization. The task result contains a <see cref="IDbContextTransaction" /> that represents the started transaction.
/// </returns>
/// <exception cref="OperationCanceledException">If the <see cref="CancellationToken" /> is canceled.</exception>
public static Task<IDbContextTransaction> BeginTransactionAsync(this DbContext dbContext, CancellationToken cancellationToken)
{
if (dbContext.Database.GetProviderType() == DatabaseFacadeExtensions.DatabaseProvider.InMemory)
return Task.FromResult<IDbContextTransaction>(new DbContextTransactionStub());
return dbContext.Database.BeginTransactionAsync(cancellationToken);
}
/// <inheritdoc cref="IDbContextTransaction" />
private class DbContextTransactionStub : IDbContextTransaction
{
/// <inheritdoc />
public Guid TransactionId { get; private set; } = Guid.NewGuid();
/// <inheritdoc />
public void Commit()
{ }
/// <inheritdoc />
public Task CommitAsync(CancellationToken cancellationToken = default)
=> Task.CompletedTask;
/// <inheritdoc />
public void Dispose()
{ }
/// <inheritdoc />
public ValueTask DisposeAsync()
=> new(Task.CompletedTask);
/// <inheritdoc />
public void Rollback()
{ }
/// <inheritdoc />
public Task RollbackAsync(CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
}
}