dotnet/efcore · error · InvalidOperationException
Relational-specific methods can only be used when the…
Error message
Relational-specific methods can only be used when the context is using a relational database provider.
What it means
Thrown by RelationalDatabaseFacadeExtensions.UseTransaction(DbTransaction, Guid) when the context's transaction manager is not an IRelationalTransactionManager — meaning the context is not using a relational database provider (e.g. it is using the InMemory provider). Relational transaction APIs only work when a relational provider is registered.
Solutions
- Use a relational provider (UseSqlServer, UseSqlite, UseNpgsql, etc.) so the transaction manager is relational.
- Guard relational transaction calls behind a check of whether the provider is relational.
- Remove UseTransaction calls in test scenarios that run against the InMemory provider.
Example fix
// before: InMemory provider cannot accept a DbTransaction
optionsBuilder.UseInMemoryDatabase("test");
context.Database.UseTransaction(existingDbTransaction, id); // throws
// after: use a relational provider in the scenario needing transactions
optionsBuilder.UseSqlite("DataSource=:memory:");
context.Database.UseTransaction(existingDbTransaction, id); Defensive patterns
Strategy: validation
Validate before calling
// Only enlist a DbTransaction when the provider is relational
var provider = context.Database.GetService<IRelationalConnection>();
if (provider != null)
context.Database.UseTransaction(dbTransaction, transactionId);
else
throw new InvalidOperationException("Context is not using a relational provider."); Type guard
static bool IsRelational(DbContext c)
=> c.Database.GetService<IRelationalDatabaseFacadeDependencies>() != null; Prevention
- Use a relational provider wherever transaction APIs are needed.
- Branch transaction enlistment behind an IsRelational check in shared code.
- Keep UseTransaction calls out of InMemory-based test paths.
When it happens
Trigger: Calling Database.UseTransaction(dbTransaction, transactionId) on a context whose provider is non-relational (Microsoft.EntityFrameworkCore.InMemory, or a non-relational custom provider).
Common situations: Unit tests using UseInMemoryDatabase that also call UseTransaction; switching a context from SQL Server/SQLite to InMemory without removing transaction-management code; a provider that does not implement IRelationalTransactionManager.
Related errors
- Multiple relational database provider configurations found…
- No relational database providers are configured. Configure…
- The provider ' ' is not a Relational provider and therefore…
- Timeout must be greater than or equal to zero. Provided…
- Cosmos-specific methods can only be used when the context…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/e26980ac87d59e50.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs:875
=> databaseFacade.UseTransaction(transaction, Guid.NewGuid());
/// <summary>
/// Sets the <see cref="DbTransaction" /> to be used by database operations on the <see cref="DbContext" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-transactions">Transactions in EF Core</see> for more information and examples.
/// </remarks>
/// <param name="databaseFacade">The <see cref="DatabaseFacade" /> for the context.</param>
/// <param name="transaction">The <see cref="DbTransaction" /> to use.</param>
/// <param name="transactionId">The unique identifier for the transaction.</param>
/// <returns>A <see cref="IDbContextTransaction" /> that encapsulates the given transaction.</returns>
public static IDbContextTransaction? UseTransaction(
this DatabaseFacade databaseFacade,
DbTransaction? transaction,
Guid transactionId)
=> databaseFacade.GetTransactionManager() is IRelationalTransactionManager relationalTransactionManager
? relationalTransactionManager.UseTransaction(transaction, transactionId)
: throw new InvalidOperationException(RelationalStrings.RelationalNotInUse);
/// <summary>
/// Sets the <see cref="DbTransaction" /> to be used by database operations on the <see cref="DbContext" />.
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-transactions">Transactions in EF Core</see> for more information and examples.
/// </remarks>
/// <param name="databaseFacade">The <see cref="DatabaseFacade" /> for the context.</param>
/// <param name="transaction">The <see cref="DbTransaction" /> to use.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
/// <returns>A <see cref="Task" /> containing the <see cref="IDbContextTransaction" /> for the given transaction.</returns>
/// <exception cref="OperationCanceledException">If the <see cref="CancellationToken" /> is canceled.</exception>
public static Task<IDbContextTransaction?> UseTransactionAsync(
this DatabaseFacade databaseFacade,
DbTransaction? transaction,
CancellationToken cancellationToken = default)
=> databaseFacade.UseTransactionAsync(transaction, Guid.NewGuid(), cancellationToken);
View on GitHub (pinned to 3a2006ef56)