Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对System.Transactions.TransactionScope的Npgsql 4.x支持不起作用?_C#_Postgresql_Transactions_Npgsql - Fatal编程技术网

C# 对System.Transactions.TransactionScope的Npgsql 4.x支持不起作用?

C# 对System.Transactions.TransactionScope的Npgsql 4.x支持不起作用?,c#,postgresql,transactions,npgsql,C#,Postgresql,Transactions,Npgsql,我们有一个基于web的多层电子健康系统平台,它使用类/对象层次结构。例如,“患者门诊就诊”对象可能包括多个诊断对象、多个药物对象、多个观察对象、实验室测试对象等。使用.NET System.transactions.TransactionScope处理数据库事务 将数据持久化到数据库中时,层次结构中的每个嵌套对象: 实例化TransactionScope(使用默认事务 必需选项) 实例化NpgsqlConnection连接 有自己的SQL和 如果一切顺利,则设置TransactionScope.

我们有一个基于web的多层电子健康系统平台,它使用类/对象层次结构。例如,“患者门诊就诊”对象可能包括多个诊断对象、多个药物对象、多个观察对象、实验室测试对象等。使用.NET System.transactions.TransactionScope处理数据库事务

将数据持久化到数据库中时,层次结构中的每个嵌套对象:

  • 实例化TransactionScope(使用默认事务 必需选项)
  • 实例化NpgsqlConnection连接
  • 有自己的SQL和
  • 如果一切顺利,则设置TransactionScope.Complete()
  • 为了简化,对象层次结构中的对象与下面的代码示例类似:

    void RootMethod()
    {
        using(TransactionScope scope = new TransactionScope())
        {
            /* Perform transactional work here */
            SomeMethod();
            AnotherMethod();
    
            scope.Complete();
        }
    }
    
    void SomeMethod()
    {
        using(TransactionScope scope = new TransactionScope())
        {
            using(NpgsqlConnection connection = new NpgsqlConnection(connectionString))
            {
                connection.Open()
                /* Perform transactional work here */
                scope.Complete();
            }
        }
    }
    
    void AnotherMethod()
    {
        using(TransactionScope scope = new TransactionScope())
        {
            using(NpgsqlConnection connection = new NpgsqlConnection(connectionString))
            {
                connection.Open()
                /* Perform transactional work here */
                scope.Complete();
            }
        }
    }
    
    封装在“using(TransactionScope scope=new TransactionScope()){…}”代码块中的程序代码在Oracle(使用db Oracle驱动程序)上被登记在相同的事务中,但在Postgres上使用Npgsql时,将生成单独的事务,而不是一个事务

    因此,Postgres上的事务会因外键约束而失败—数据无法持久化到子表中,因为创建的单独事务在父对象提交数据之前没有看到插入父表(在单独事务中)的数据

    我们在Npgsql connectString中得到了inclist=true,并且在我们的Postgres服务器上,服务器参数max_prepared_transactions设置为大于0的值

    我们测试的Npgsql驱动程序版本是4.0.7和4.1.2。我们的devt环境中的Postgres服务器版本是版本10

    Npgsql文档说System.Transactions.TransactionScope是受支持的(并且从v3.3开始就受到支持),我们在StackOverflow上搜索的其他Npgsql相关答案也是如此

    乍一看,在事务性单元测试中似乎只使用一个数据库连接

    问题:

    • 根据TransactionScope实施指南(例如),Npgsql是否支持多个TransactionScope和多个参与数据库连接
    • 有什么明显的遗漏吗

    如上所述,使用Npgsql 4.x,在“使用(TransactionScope=new TransactionScope()){…}”中打开每个数据库连接代码块似乎会生成一个新事务,而不是登记在同一个事务中。

    在内部事务范围中打开第二个NpgsqlConnection之前,需要关闭在外部事务范围中打开的NpgsqlConnection(允许Npgsql在内部重用相同的物理连接,而不会升级到分布式事务)。

    在内部事务范围中打开第二个NpgsqlConnection之前,需要关闭在外部事务范围中打开的NpgsqlConnection(允许Npgsql在内部重用相同的物理连接,而不会升级到分布式事务).

    使用最新的Npgsql版本运行上面提供的代码只会触发一个事务,如PG日志所示;SomeMethod和AnotherMethod中的嵌套作用域实际上并不创建事务-它们只是在RootMethod中加入根作用域,它们对完成的调用只是对提交的投票。请注意,您不需要要将max_prepared_transactions设置为非零:上面的代码示例应在不升级为分布式事务的情况下工作。这是因为在(根目录)中只有一个打开的连接事务作用域在给定的时间点,因此Npgsql在内部重用相同的物理连接。如果同时打开两个连接,则会升级到分布式事务(然后我们就处于完全不同的世界中)。请尝试重新检查您认为实际上正在创建多个数据库事务的原因。谢谢Shay,这非常有帮助-为我们指出了代码中的问题。我上面的简化代码说明不太准确(我的错误):看来我们确实在根TransactionScope中打开了一个NpgsqlConnection,但在内部TransactionScope打开第二个NpgsqlConnection之前,我们没有关闭该连接-实际上导致了一个分布式(两个单独的)事务,这是无意的。因此,在同一个数据库上(在Oracle上),单独的程序代码块看不到彼此工作.@shay Rojansky运行您在上面提供的最新Npgsql版本的代码只会触发一个事务,如PG日志所示;,您在SomeMethod和AnotherMethod中的嵌套作用域实际上并不创建事务-它们只是在RootMethod中加入根作用域,它们对Complete的调用只是对commit的投票ld不需要将max_prepared_transactions设置为非零:上面的代码示例应在不升级为分布式事务的情况下工作。这是因为您在(根目录)中只有一个打开的连接事务作用域在给定的时间点,因此Npgsql在内部重用相同的物理连接。如果同时打开两个连接,则会升级到分布式事务(然后我们就处于完全不同的世界中)。请尝试重新检查您认为实际上正在创建多个数据库事务的原因。谢谢Shay,这非常有帮助-为我们指出了代码中的问题。我上面的简化代码说明不太准确(我的错误):看来我们确实在根TransactionScope中打开了一个NpgsqlConnection,但在内部TransactionScope打开第二个NpgsqlConnection之前,我们没有关闭该连接-实际上导致了一个分布式(两个单独的)事务,这是无意的。因此,在同一个数据库上(在Oracle上),单独的程序代码块看不到彼此工作。@shay rojansky