{"record":{"id":"808a87924c700d30","repo":"dotnet/efcore","slug":"user-transaction-is-not-supported-with-a-transacti","errorCode":null,"errorMessage":"User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy.","messagePattern":"User transaction is not supported with a TransactionSuppressed migrations or a retrying execution strategy\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs","lineNumber":52,"sourceCode":"\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public virtual int ExecuteNonQuery(\n        IReadOnlyList<MigrationCommand> migrationCommands,\n        IRelationalConnection connection,\n        MigrationExecutionState executionState,\n        bool commitTransaction,\n        IsolationLevel? isolationLevel = null)\n    {\n        var inUserTransaction = connection.CurrentTransaction is not null && executionState.Transaction == null;\n        if (inUserTransaction\n            && (migrationCommands.Any(x => x.TransactionSuppressed) || executionStrategy.RetriesOnFailure))\n        {\n            throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction);\n        }\n\n        using var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled);\n\n        return executionStrategy.Execute(\n            (migrationCommands, connection, inUserTransaction, executionState, commitTransaction, isolationLevel),\n            static (_, s) => Execute(\n                s.migrationCommands,\n                s.connection,\n                s.executionState,\n                beginTransaction: !s.inUserTransaction,\n                commitTransaction: !s.inUserTransaction && s.commitTransaction,\n                s.isolationLevel),\n            verifySucceeded: null);\n    }\n\n    private static int Execute(\n        IReadOnlyList<MigrationCommand> migrationCommands,","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs#L34-L70","documentation":"Migrations cannot run inside a user-supplied transaction when either (a) any migration command is transaction-suppressed, or (b) the execution strategy retries on failure. Both require EF to control transaction boundaries, which is impossible while the caller holds its own transaction.","triggerScenarios":"Calling Migrate()/MigrateAsync() (or the lower-level IMigrationCommandExecutor.ExecuteNonQuery) while a user transaction is active on the connection (connection.CurrentTransaction set, executionState.Transaction null), and at least one command has TransactionSuppressed or the execution strategy has RetriesOnFailure.","commonSituations":"Wrapping Database.Migrate() in an outer IDbContextTransaction; using SQL Server's retrying ExecutionStrategy together with migrations; manually opening a transaction before EnsureCreated/Migrate in startup code.","solutions":["Do not open a user transaction around migrations; let EF manage the migration transaction.","If you must retry, rely on the retrying execution strategy without an outer user transaction.","Avoid TransactionSuppressed migration commands when running migrations programmatically inside app transactions.","Move Migrate() outside any ambient TransactionScope before calling it."],"exampleFix":"// before\nusing var tx = context.Database.BeginTransaction();\nawait context.Database.MigrateAsync(); // throws\n\n// after\nawait context.Database.MigrateAsync();\n// run app logic / transactions after migrations complete","handlingStrategy":"validation","validationCode":"bool hasUserTx = context.Database.CurrentTransaction is not null;\nbool retries = context.Database.GetExecutionStrategy().RetriesOnFailure;\nif (!hasUserTx)\n{\n    context.Database.Migrate();\n}","typeGuard":"static bool CanMigrateInCurrentState(DbContext context, IEnumerable<MigrationCommand> cmds)\n    => context.Database.CurrentTransaction is null\n       || (!cmds.Any(c => c.TransactionSuppressed)\n           && !context.Database.GetExecutionStrategy().RetriesOnFailure);","tryCatchPattern":null,"preventionTips":["Run migrations outside any user transaction or ambient TransactionScope.","Do not combine a retrying execution strategy with manual transaction management for migrations.","Keep startup migration calls before any application-level transaction work."],"tags":["ef-core","migrations","transactions","execution-strategy","retry"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}