From 0946237df5e2b613284198efb6c4e40dbe9bc6ff Mon Sep 17 00:00:00 2001 From: Shady Nagy Date: Thu, 29 Jan 2026 01:25:39 +0400 Subject: [PATCH 1/5] Add IsolationLevel overloads to InMemoryTransactionManager Add BeginTransaction(IsolationLevel) and BeginTransactionAsync(IsolationLevel, CancellationToken) that delegate to existing parameterless methods, ignoring the isolation level parameter. This makes InMemory provider behavior consistent - transactions are already ignored, so isolation levels should be ignored too instead of throwing. --- .../Internal/InMemoryTransactionManager.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs index d07bc94abbb..8728733bb02 100644 --- a/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs +++ b/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Data; using System.Transactions; using Microsoft.EntityFrameworkCore.InMemory.Internal; @@ -55,6 +56,44 @@ public virtual Task BeginTransactionAsync( return Task.FromResult(StubTransaction); } + /// + /// 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. + /// + /// + /// The parameter is ignored by the in-memory provider since + /// transactions are not supported. This method exists to allow code that uses transactions with + /// isolation levels to work seamlessly with the in-memory provider for testing purposes. + /// + /// The to use (ignored by this provider). + /// A that represents a no-op transaction. + public virtual IDbContextTransaction BeginTransaction(IsolationLevel isolationLevel) + => BeginTransaction(); + + /// + /// 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. + /// + /// + /// The parameter is ignored by the in-memory provider since + /// transactions are not supported. This method exists to allow code that uses transactions with + /// isolation levels to work seamlessly with the in-memory provider for testing purposes. + /// + /// The to use (ignored by this provider). + /// A to observe while waiting for the task to complete. + /// + /// A task that represents the asynchronous operation. The task result contains a + /// that represents a no-op transaction. + /// + public virtual Task BeginTransactionAsync( + IsolationLevel isolationLevel, + CancellationToken cancellationToken = default) + => BeginTransactionAsync(cancellationToken); + /// /// 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 From ee07857d83934d061ce94c0cf367841f19551c61 Mon Sep 17 00:00:00 2001 From: Shady Nagy Date: Thu, 29 Jan 2026 01:42:20 +0400 Subject: [PATCH 2/5] Add tests for IsolationLevel overloads in InMemoryTransactionManager Add tests for BeginTransaction(IsolationLevel) and BeginTransactionAsync(IsolationLevel). --- .../Storage/InMemoryTransactionManagerTest.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs b/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs index 7e17753ba74..b6bbdffe9e6 100644 --- a/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs +++ b/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Data; using System.Transactions; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.InMemory.Diagnostics.Internal; @@ -97,6 +98,14 @@ public void Throws_on_RollbackTransaction() public void Throws_on_RollbackTransactionAsync() => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).RollbackTransactionAsync().GetAwaiter().GetResult()); + [ConditionalFact] + public void Throws_on_BeginTransaction_with_IsolationLevel() + => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransaction(IsolationLevel.Serializable)); + + [ConditionalFact] + public void Throws_on_BeginTransactionAsync_with_IsolationLevel() + => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransactionAsync(IsolationLevel.Serializable).GetAwaiter().GetResult()); + private static void AssertThrows(Action action) => Assert.Equal( CoreStrings.WarningAsErrorTemplate( From f96dfa3e6ae43e7ca12263d90dfaf7937ec0711e Mon Sep 17 00:00:00 2001 From: Shady Nagy Date: Thu, 29 Jan 2026 02:27:34 +0400 Subject: [PATCH 3/5] Update InMemoryTransactionManager.cs for using --- .../Storage/Internal/InMemoryTransactionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs b/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs index 8728733bb02..211bf6e73ce 100644 --- a/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs +++ b/src/EFCore.InMemory/Storage/Internal/InMemoryTransactionManager.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Data; using System.Transactions; using Microsoft.EntityFrameworkCore.InMemory.Internal; +using IsolationLevel = System.Data.IsolationLevel; namespace Microsoft.EntityFrameworkCore.InMemory.Storage.Internal; From 087b1994d414f00512361406c678c7f0e90b83a6 Mon Sep 17 00:00:00 2001 From: Shady Nagy Date: Thu, 29 Jan 2026 02:28:48 +0400 Subject: [PATCH 4/5] Update InMemoryTransactionManagerTest.cs fix using --- .../Storage/InMemoryTransactionManagerTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs b/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs index b6bbdffe9e6..18d8ab6efaf 100644 --- a/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs +++ b/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs @@ -1,12 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Data; using System.Transactions; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.InMemory.Diagnostics.Internal; using Microsoft.EntityFrameworkCore.InMemory.Internal; using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal; +using IsolationLevel = System.Data.IsolationLevel; // ReSharper disable InconsistentNaming namespace Microsoft.EntityFrameworkCore.Storage; From 860eb7d78e86741058b1835027c7a332d9f74251 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Thu, 29 Jan 2026 09:47:13 +0100 Subject: [PATCH 5/5] Move tests --- .../Storage/InMemoryTransactionManagerTest.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs b/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs index 18d8ab6efaf..ca6bfe8c5f3 100644 --- a/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs +++ b/test/EFCore.InMemory.Tests/Storage/InMemoryTransactionManagerTest.cs @@ -82,6 +82,14 @@ public void Throws_on_BeginTransaction() public void Throws_on_BeginTransactionAsync() => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransactionAsync().GetAwaiter().GetResult()); + [ConditionalFact] + public void Throws_on_BeginTransaction_with_IsolationLevel() + => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransaction(IsolationLevel.Serializable)); + + [ConditionalFact] + public void Throws_on_BeginTransactionAsync_with_IsolationLevel() + => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransactionAsync(IsolationLevel.Serializable).GetAwaiter().GetResult()); + [ConditionalFact] public void Throws_on_CommitTransaction() => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).CommitTransaction()); @@ -98,14 +106,6 @@ public void Throws_on_RollbackTransaction() public void Throws_on_RollbackTransactionAsync() => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).RollbackTransactionAsync().GetAwaiter().GetResult()); - [ConditionalFact] - public void Throws_on_BeginTransaction_with_IsolationLevel() - => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransaction(IsolationLevel.Serializable)); - - [ConditionalFact] - public void Throws_on_BeginTransactionAsync_with_IsolationLevel() - => AssertThrows(() => new InMemoryTransactionManager(CreateLogger()).BeginTransactionAsync(IsolationLevel.Serializable).GetAwaiter().GetResult()); - private static void AssertThrows(Action action) => Assert.Equal( CoreStrings.WarningAsErrorTemplate(