using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Storage;
namespace Microsoft.EntityFrameworkCore
{
///
/// Extensions for the .
///
public static class DbContextExensions
{
///
/// Starts a new transaction.
///
///
/// See Transactions in EF Core for more information.
///
/// The current .
///
/// A that represents the started transaction.
///
public static IDbContextTransaction BeginTransaction(this DbContext dbContext)
{
if (dbContext.Database.GetProviderType() == DatabaseFacadeExtensions.DatabaseProvider.InMemory)
return new DbContextTransactionStub();
return dbContext.Database.BeginTransaction();
}
///
/// Asynchronously starts a new transaction.
///
///
///
/// 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 Avoiding DbContext threading issues
/// for more information.
///
///
/// See Transactions in EF Core for more information.
///
///
/// The current .
/// A to observe while waiting for the task to complete.
///
/// A task that represents the asynchronous transaction initialization. The task result contains a that represents the started transaction.
///
/// If the is canceled.
public static Task BeginTransactionAsync(this DbContext dbContext, CancellationToken cancellationToken)
{
if (dbContext.Database.GetProviderType() == DatabaseFacadeExtensions.DatabaseProvider.InMemory)
return Task.FromResult(new DbContextTransactionStub());
return dbContext.Database.BeginTransactionAsync(cancellationToken);
}
///
private class DbContextTransactionStub : IDbContextTransaction
{
///
public Guid TransactionId { get; private set; } = Guid.NewGuid();
///
public void Commit()
{ }
///
public Task CommitAsync(CancellationToken cancellationToken = default)
=> Task.CompletedTask;
///
public void Dispose()
{ }
///
public ValueTask DisposeAsync()
=> new(Task.CompletedTask);
///
public void Rollback()
{ }
///
public Task RollbackAsync(CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
}
}