Rus*_*nov 4 c# postgresql transactionscope npgsql dapper
我的 Postgres 数据库中有一些主表(如公司)和许多从属表(如 CompanyAddresses、CompanyPaymentInfos 等):
CREATE TABLE Companies (
Id uuid NOT NULL PRIMARY KEY,
...);
CREATE TABLE CompanyAddresses(
CompanyId uuid NOT NULL PRIMARY KEY REFERENCES Companies(Id),
...);
CREATE TABLE CompanyPaymentInfos(
CompanyId uuid NOT NULL PRIMARY KEY REFERENCES Companies(Id),
...);
Run Code Online (Sandbox Code Playgroud)
我在 C# 代码中使用标准库中的事务:
private TransactionScope GeTransactionScope()
{
return new TransactionScope(
TransactionScopeOption.RequiresNew,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadCommitted
},
TransactionScopeAsyncFlowOption.Enabled);
}
private async Task DoChange(...)
{
using (var scope = GeTransactionScope())
{
await Insert(Company);
await Task.WhenAll(
Insert(CompanyPaymentInfo),
Insert(CompanyAddress),
Insert(CompanyTags),
// so on
);
scope.Complete();
}
}
Run Code Online (Sandbox Code Playgroud)
每个Insert命令只产生 SQL 代码的执行,没有任何内部事务。
在 DoChange 执行后,我收到此错误:
Npgsql.PostgresException (0x80004005): 23503: 在表“companyaddresses”上插入或更新违反外键约束“companyaddresses_companyid_fkey”
当然,我有很多问题,例如:
如果我DoChange改为顺序执行,一切正常:
private void DoChange()
{
using (var scope = GeTransactionScope())
{
await Insert(Company);
await Insert(CompanyPaymentInfo);
await Insert(CompanyAddress);
await Insert(CompanyTags);
// ...
scope.Complete();
}
}
Run Code Online (Sandbox Code Playgroud)
也许它有帮助:
enlist=true到我的连接字符串以使事务工作。Insert命令中使用 Npgsql 3.2.5 和 Dapper 1.50.2这里没有什么神奇之处,您会收到错误消息,因为您在插入 CompanyAddress 时使用的连接不是您认为的那个。
这是一个新的连接。运行 ComapnyPaymentInfo insert 时,您正在使用已绑定到您的交易的连接。它正在等待新命令,因为您已在上一步中等待。
另一方面,使用 Task.WhenAll() 将尝试使用多个线程。如果一个连接忙于运行一个命令,它将不会被使用,并且会产生一个新的。
请记住,在使用事务时,您只有一个可用连接,您无法从并行性中受益。