内存中的 Sqlite - TransactionScope - 已检测到环境事务
Posted
技术标签:
【中文标题】内存中的 Sqlite - TransactionScope - 已检测到环境事务【英文标题】:Sqlite in-memory - TransactionScope - ambient transaction has been detected 【发布时间】:2020-05-21 15:39:30 【问题描述】:我遇到了异常
Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning: 检测到环境事务
但我不知道如何解决此异常。当我在TransactionScope
中调用SaveChanges()
时,我的代码失败了。可能是因为TransactionScope
本身在SQLite context
事务里面,但是这个问题怎么处理呢?
我要测试的方法
它使用 TransactionScope,因为我想确定,当我与他一起操作时,加载的对象(Request
类)不会改变。
public void Handle(Create cmd)
// Wrap via transaction
using (var transaction = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions IsolationLevel = IsolationLevel.RepeatableRead ))
// Load request object from repository.
Request request = _repository.Find(cmd.RequestId);
// Create detail object
var detail = new Detail(requestId: cmd.RequestId);
// Add created detail object into Request object
request.CreateDetail(detail);
// Save request into repository.
_repository.SaveChanges(); // <--- HERE IS THE EXCEPTION THROWN
// Commit transaction
transaction.Complete();
我要执行的测试方法 它使用 SQLite 内存中的关系数据库,因为 TransactionScope 不支持非关系数据库。
[Fact]
public void Create()
// Arrange
// ---------------------------------------------------------------------
var request = new Request();
using (var connection = new SqliteConnection("DataSource=:memory:"))
connection.Open();
var options = new DbContextOptionsBuilder<SamplesContext>()
.UseSqlite(connection)
.Options;
using (var context = new SamplesContext(options))
context.Database.EnsureCreated();
var service = SetupDetailService(context);
context.Request.Add(request);
context.SaveChanges();
var storedRequest = context.Request.FirstOrDefault();
var createCommand = new Create(requestId: Convert.ToInt32(storedRequest.Id));
// Act
// ---------------------------------------------------------------------
service.Handle(createCommand); // <--- HERE IS THE EXCEPTION THROWN
context.SaveChanges();
// Assert
// ----------------------------------------------------------------------
// ...
;
;
【问题讨论】:
【参考方案1】:我阻止了错误以运行测试:
var builder = new DbContextOptionsBuilder<EpsOnlineDbContext>();
DbConnection connection = new SqliteConnection("DataSource=:memory:");
connection.OpenAsync().GetAwaiter().GetResult();
builder.UseSqlite(connection);
builder.ConfigureWarnings(x => x.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.AmbientTransactionWarning));
【讨论】:
如果您使用的是 EF Core 3 或更高版本,则此方法有效。如果您使用的是 EF Core 2.x,上面的代码将清除环境警告,但随后您将收到 System.NotSupportedException 消息。这是 2.x 中未修复的错误,解决它的唯一方法是切换到在内存 DB 中使用 EF(不理想)或迁移到 EF Core 3 或更高版本。请参阅github.com/dotnet/efcore/issues/15413 了解更多信息。 根据我的经验,builder.ConfigureWarnings()
应该在 builder.UseSqlite()
之前。以上是关于内存中的 Sqlite - TransactionScope - 已检测到环境事务的主要内容,如果未能解决你的问题,请参考以下文章
FireDAC 下的 Sqlite [7] - 备份优化事务(Transaction)/
在 SQLite + BEGIN TRANSACTION 中更新更快
错误:未定义不是 ReactNative 中的对象(评估“db.transaction”)