dotnet/efcore · error · NotSupportedException
The Cosmos database provider does not support transactions.
Error message
The Cosmos database provider does not support transactions.
What it means
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.
Source
Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosTransactionManager.cs:24
namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public class CosmosTransactionManager : IDbContextTransactionManager, ITransactionEnlistmentManager
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual IDbContextTransaction BeginTransaction()
=> throw new NotSupportedException(CosmosStrings.TransactionsNotSupported);
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual Task<IDbContextTransaction> BeginTransactionAsync(
CancellationToken cancellationToken = default)
=> throw new NotSupportedException(CosmosStrings.TransactionsNotSupported);
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual void CommitTransaction()View on GitHub (pinned to dbf9771522)
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.
Example fix
// before
using var tx = db.Database.BeginTransaction();
try { await db.SaveChangesAsync(); tx.Commit(); }
catch { tx.Rollback(); throw; } // NotSupportedException on Cosmos
// after
await db.SaveChangesAsync(); // Cosmos: each document save is atomic; no tx wrapper
// or guard:
if (db.Database.ProviderName != "Microsoft.EntityFrameworkCore.Cosmos")
{
using var tx = db.Database.BeginTransaction();
await db.SaveChangesAsync();
tx.Commit();
}
else
{
await db.SaveChangesAsync();
} Defensive patterns
Strategy: validation
Validate before calling
// Skip transaction wrapping on Cosmos
var useTx = db.Database.ProviderName != "Microsoft.EntityFrameworkCore.Cosmos";
if (useTx)
{
using var tx = db.Database.BeginTransaction();
try { db.SaveChanges(); tx.Commit(); }
catch { tx.Rollback(); throw; }
}
else
{
db.SaveChanges();
} Type guard
static bool SupportsTransactions(DbContext db)
=> db.Database.ProviderName != "Microsoft.EntityFrameworkCore.Cosmos"; Try / catch
try
{
if (db.Database.ProviderName != "Microsoft.EntityFrameworkCore.Cosmos")
using (db.Database.BeginTransaction()) { db.SaveChanges(); }
else
db.SaveChanges();
}
catch (NotSupportedException ex) when (ex.Message.Contains("does not support transactions"))
{
// Fallback: save without transaction (Cosmos saves are per-document atomic)
db.SaveChanges();
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- The property '{1_entityType}.{0_property}' contains null, bu
- When using AutoTransactionBehavior.Always with the Cosmos DB
- When using AutoTransactionBehavior.Always with the Cosmos DB
- The entity of type '{entityType}' is mapped as part of the d
- Azure Cosmos DB does not support synchronous I/O. Make sure
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/0d1a5ad69de085cf.
Report an issue: GitHub.