我的控制器代码类似于以下内容(此处匿名)。我预计由于 EF Core 6 中缺乏分布式事务支持而引发异常,并且由于使用两个不同的
DbConnection
和两个不同的 DbContext
,我预计代码会尝试将事务升级为分布式事务s 在同一事务中。我调试并验证了两个不同的连接具有不同的进程ID,因此它似乎与连接池无关。为什么这段代码看起来有效?
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Npgsql;
namespace Controllers.Test;
[Route("test")]
public sealed class TestController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IHostEnvironment _host;
public TestController(
IConfiguration configuration,
IHostEnvironment host)
{
_configuration = configuration;
_host = host;
}
[HttpGet]
public void Get()
{
using var transactionScope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TimeSpan.FromMinutes(30) },
TransactionScopeAsyncFlowOption.Enabled);
var fooConnectionString = _configuration.GetConnectionString("foo")!;
var barConnectionString = _configuration.GetConnectionString("bar")!;
using var fooConnection = new NpgsqlConnection(fooConnectionString);
using var barConnection = new NpgsqlConnection(barConnectionString);
fooConnection.Open();
barConnection.Open();
using var fooDbContext = new FooDbContext(new DbContextOptionsBuilder<FooDbContext>()
.UseNpgsql(fooConnection, o => o.UseNodaTime())
.Options);
using var barDbContext = new BarDbContext(new DbContextOptionsBuilder<BarDbContext>()
.UseNpgsql(barConnection, o => o.UseNodaTime())
.Options);
var foo = fooDbContext.Foos.OrderBy(x => x.Id).First();
foo.SequenceNumber++;
fooDbContext.SaveChanges();
var bar = barDbContext.Bars.OrderBy(x => x.Id).First();
bar.SequenceNumber++;
barDbContext.SaveChanges();
transactionScope.Complete();
}
}
.NET Core 6
Npgsql.EntityFrameworkCore.PostgreSQL 版本 6.0.7
Microsoft.EntityFrameworkCore 版本 6.0.8
您运行的 .Net Core 版本是什么?带有 .Net Core 7 的 Windows 支持分布式事务。如果您针对 .Net Core 6 进行构建,您可能会看到预期的异常。 Npgsql 可能不完全支持它们并忽略或重新使用连接,您可以尝试:
var foo = fooDbContext.Foos.OrderBy(x => x.Id).First();
foo.SequenceNumber++;
var bar = barDbContext.Bars.OrderBy(x => x.Id).First();
bar.SequenceNumber++;
fooDbContext.SaveChanges();
barDbContext.SaveChanges();
来自 Npgsql doco:(https://www.npgsql.org/doc/basic-usage.html)
虽然Npgsql部分支持这种机制,但由于.NET支持的一些设计问题,它没有实现分布式事务的恢复部分。虽然分布式事务可能适合您,但不鼓励使用 Npgsql 完全依赖它们。