我需要在两个模型下实现事务(使用两个分离的有界上下文)。所以这样的代码:
using (TransactionScope scope = new TransactionScope())
{
//Operation 1
using(var context1 = new Context1())
{
context1.Add(someCollection1);
context1.SaveChanges();
}
//Operation 2
using(var context2 = new Context2())
{
context2.Add(someCollection2);
context2.SaveChanges();
}
scope.Complete();
}
返回异常:
检测到环境事务。实体框架核心确实如此 不支持环境事务。看到 http://go.microsoft.com/fwlink/?LinkId=800142
在链接中,他们建议在两个上下文中使用一个连接。并使用context2来使用context1的块。
但如果我为每个模型使用自己的控制器/服务:
using (TransactionScope scope = new TransactionScope())
{
service1.DoWork();
service2.DoWork();
scope.Complete();
}
我该如何实现?在方法中添加连接作为参数 - 似乎很荒谬。与连接的Init服务也是个坏主意。
答案 0 :(得分:1)
您可以像这样使用'contexts':
using (var context1 = new Context1())
{
using (var transaction = context1.Database.BeginTransaction())
{
try
{
context1.Add(someCollection1);
context1.SaveChanges();
// if we don't have errors - next step
using(var context2 = new Context2())
{
// second step
context2.Add(someCollection2);
context2.SaveChanges();
}
// if all success - commit first step (second step was success completed)
transaction.Commit();
}
catch (Exception)
{
// if we have error - rollback first step (second step not be able accepted)
transaction.Rollback();
}
}
}
如果您将使用许多控制器/服务,那么您可以使用内部方法将DbConnection
传递到您的服务方法中。您必须封装低层逻辑。
使用连接的Init服务也是个坏主意。 - 可能你是对的。但您可以尝试使用一个连接和单个事务初始化两个方法。
见下一个答案,他们可以帮助你:
答案 1 :(得分:0)
在摘要下方使用
using (var context = new MyContext())
{
using (var transaction = context.Database.BeginTransaction())
{
try
{
var customer = context.Customers
.Where(c => c.CustomerId == 2)
.FirstOrDefault();
customer.Address = "43 rue St. Laurent";
context.SaveChanges();
var newCustomer = new Customer
{
FirstName = "Elizabeth",
LastName = "Lincoln",
Address = "23 Tsawassen Blvd."
};
context.Customers.Add(newCustomer);
context.SaveChanges();
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
}
}
}
更多详细信息:https://entityframeworkcore.com/saving-data-transaction
答案 2 :(得分:0)
关于您对How should I implement this?
的声明:
using (TransactionScope scope = new TransactionScope())
{
service1.DoWork();
service2.DoWork();
scope.Complete();
}
我正在使用控制器 > 服务 > 存储库模式,我发现在使用异步选项时同样的错误已为我解决。每个存储库都按照通常的方法在 Startup.cs
中注入了一个 db 上下文。也许这是在较新版本的 .NET Core 中修复的,或者我只是在存储库中使用相同的上下文实例?以下对我有用:
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
service1.DoWork();
service2.DoWork();
scope.Complete();
}