{"record":{"id":"0d1a5ad69de085cf","repo":"dotnet/efcore","slug":"the-cosmos-database-provider-does-not-support-tran","errorCode":null,"errorMessage":"The Cosmos database provider does not support transactions.","messagePattern":"The Cosmos database provider does not support transactions\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Storage/Internal/CosmosTransactionManager.cs","lineNumber":24,"sourceCode":"\nnamespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;\n\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>\npublic class CosmosTransactionManager : IDbContextTransactionManager, ITransactionEnlistmentManager\n{\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 IDbContextTransaction BeginTransaction()\n        => throw new NotSupportedException(CosmosStrings.TransactionsNotSupported);\n\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 Task<IDbContextTransaction> BeginTransactionAsync(\n        CancellationToken cancellationToken = default)\n        => throw new NotSupportedException(CosmosStrings.TransactionsNotSupported);\n\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 void CommitTransaction()","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Cosmos/Storage/Internal/CosmosTransactionManager.cs#L6-L42","documentation":"Cosmos DB does not support distributed/ACID transactions in the way relational providers do, so the Cosmos EF Core provider's IDbContextTransactionManager.BeginTransaction() unconditionally throws NotSupportedException (CosmosStrings.TransactionsNotSupported). Cosmos only guarantees atomicity within a single stored procedure; multi-document transactions are not exposed through this provider.","triggerScenarios":"Calling dbContext.Database.BeginTransaction() (or any API that forces a transaction such as ExecuteSqlRaw inside a TransactionScope) when the Cosmos provider is registered. Any generic data-access layer that opens a transaction around SaveChanges regardless of provider will hit this on the sync path.","commonSituations":"Shared/generic repository code that wraps SaveChanges in using var tx = db.Database.BeginTransaction(); migrating from SQL Server/SQLite to Cosmos without removing the transaction wrapper; code that mixes TransactionScope with Cosmos; third-party libraries (MediatR behaviors, UoW patterns) that unconditionally open transactions.","solutions":["Remove the explicit BeginTransaction/Commit/Rollback wrapper when using the Cosmos provider; rely on SaveChanges atomicity per document.","Guard the transaction call with a provider check: if (db.Database.ProviderName != \"Microsoft.EntityFrameworkCore.Cosmos\") { ... BeginTransaction ... }.","For multi-document atomicity, encapsulate the operation in a Cosmos stored procedure instead of an EF transaction.","Refactor shared UoW code to make transaction usage opt-in per provider."],"exampleFix":"// before\nusing var tx = db.Database.BeginTransaction();\ntry { await db.SaveChangesAsync(); tx.Commit(); }\ncatch { tx.Rollback(); throw; } // NotSupportedException on Cosmos\n\n// after\nawait db.SaveChangesAsync(); // Cosmos: each document save is atomic; no tx wrapper\n// or guard:\nif (db.Database.ProviderName != \"Microsoft.EntityFrameworkCore.Cosmos\")\n{\n    using var tx = db.Database.BeginTransaction();\n    await db.SaveChangesAsync();\n    tx.Commit();\n}\nelse\n{\n    await db.SaveChangesAsync();\n}","handlingStrategy":"validation","validationCode":"// Skip transaction wrapping on Cosmos\nvar useTx = db.Database.ProviderName != \"Microsoft.EntityFrameworkCore.Cosmos\";\nif (useTx)\n{\n    using var tx = db.Database.BeginTransaction();\n    try { db.SaveChanges(); tx.Commit(); }\n    catch { tx.Rollback(); throw; }\n}\nelse\n{\n    db.SaveChanges();\n}","typeGuard":"static bool SupportsTransactions(DbContext db)\n    => db.Database.ProviderName != \"Microsoft.EntityFrameworkCore.Cosmos\";","tryCatchPattern":"try\n{\n    if (db.Database.ProviderName != \"Microsoft.EntityFrameworkCore.Cosmos\")\n        using (db.Database.BeginTransaction()) { db.SaveChanges(); }\n    else\n        db.SaveChanges();\n}\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"does not support transactions\"))\n{\n    // Fallback: save without transaction (Cosmos saves are per-document atomic)\n    db.SaveChanges();\n}","preventionTips":["Branch data-access code on ProviderName before opening transactions.","Keep transaction logic in a relational-specific repository implementation.","Do not wrap SaveChanges in transactions for Cosmos at all.","Abstract IDbContextTransactionManager behind a provider-aware interface."],"tags":["cosmos","transaction","notsupported","savechanges","efcore"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}