在使用 UseTransaction 时,在原始事务之后,不会释放另一个 DbContext 上的 EF Core 事务

An EF Core transaction on the other DbContext isn't disposed after the original one is when using UseTransaction

提问人:Michal Diviš 提问时间:6/2/2023 最后编辑:Michal Diviš 更新时间:6/2/2023 访问量:69

问:

这是我前几天遇到的一个有趣的行为。我正在使用 EF Core 的方法与另一个共享事务。我遇到的问题是,即使在原始事务被处置后,另一个上下文也会保留事务,这导致了一些意想不到的错误。更重要的是,这个问题似乎只在使用SQLite时才会发生,SQL Server工作正常。UseTransactionDbContext

以下是该应用正在执行的操作的简短版本:

var connectionString = $"Data Source={Guid.NewGuid()};Mode=Memory;Cache=Shared";
var keepAliveConnection = new SqliteConnection(connectionString);
keepAliveConnection.Open();

var dbContext1 = new DbContext1(
    new DbContextOptionsBuilder<DbContext1>()
        .UseSqlite(connectionString)
        .Options);

var dbContext2 = new DbContext2(
    new DbContextOptionsBuilder<DbContext2>()
        .UseSqlite(dbContext1.Database.GetDbConnection())
        .Options);

using (var transaction = dbContext1.Database.BeginTransaction())
{
    dbContext2.Database.UseTransaction(transaction.GetDbTransaction());

    // ... do some work

    await transaction.CommitAsync();
}

Debug.Assert(dbContext2.Database.CurrentTransaction is null); // this fails

这是我得到的例外:

The transaction object is not associated with the same connection object as this command.

at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__19_0(DbContext _, Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Single[TSource](IQueryable`1 source, Expression`1 predicate)
at Company.DomainEvents.Services.GenericDomainEventService`4.UpdateEventStatus(Guid eventId, PublisherEventState status) in C:\Repos\domainevents\src\Company.DomainEvents\Services\GenericDomainEventService.cs:line 198
at Company.DomainEvents.Services.GenericDomainEventService`4.MarkEventAsInProgress(Guid eventId) in C:\Repos\domainevents\src\Company.DomainEvents\Services\GenericDomainEventService.cs:line 192
at Company.DomainEvents.Services.GenericDomainEventService`4.<PublishDomainEvent>d__8.MoveNext() in C:\Repos\domainevents\src\Company.DomainEvents\Services\GenericDomainEventService.cs:line 112

修复/解决方法

处置 返回的事务似乎可以解决问题。虽然我不是很有信心这是正确的解决方案......为了解决这个问题,我只修改了一行:dbContext2.Database.UseTransaction

dbContext2.Database.UseTransaction(transaction.GetDbTransaction());

对此:

using var _ = dbContext2.Database.UseTransaction(transaction.GetDbTransaction());

现在,另一个上下文的事务将与原始事务一样被处置。

C# SQLite 实体框架核心 SQL事务

评论


答: 暂无答案