dotnet/efcore · error · InvalidOperationException

Relational-specific methods can only be used when the contex

Error message

Relational-specific methods can only be used when the context is using a relational database provider.

What it means

Thrown by DatabaseFacade.UseTransaction(DbTransaction, Guid) when the context's transaction manager is not an IRelationalTransactionManager, i.e. the context is using a non-relational provider (e.g. in-memory or Cosmos). Relational transaction APIs only work with relational providers.

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 dbf9771522)

Solutions

  1. Use a relational provider (SqlServer, Sqlite, etc.) when transaction sharing is required.
  2. Guard the call with databaseFacade.IsRelational() before invoking UseTransaction.
  3. In tests, replace transaction-sharing logic with a relational test database or skip it for in-memory.
  4. Ensure the correct UseSqlServer/UseSqlite call is active in OnConfiguring for the environment.

Example fix

// before
db.Database.UseTransaction(existingDbTransaction); // throws in tests

// after
if (db.Database.IsRelational())
    await db.Database.UseTransactionAsync(existingDbTransaction);
Defensive patterns

Strategy: type-guard

Validate before calling

if (db.Database.IsRelational())
    db.Database.UseTransaction(transaction, transactionId);

Type guard

static bool CanShareTransaction(DatabaseFacade f) => f.IsRelational();

Prevention

When it happens

Trigger: Calling UseTransaction with an ambient DbTransaction on a context backed by a non-relational provider (RelationalDatabaseFacadeExtensions.cs:873-875). The cast to IRelationalTransactionManager fails, so RelationalNotInUse is thrown.

Common situations: Using the in-memory provider in tests while code paths call UseTransaction; switching provider config at runtime; Cosmos DB provider used with relational transaction sharing code; environment-specific provider selection (Test vs Prod) where tests use in-memory.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/e26980ac87d59e50. Report an issue: GitHub.