C# “获取异常”;重复交易标识符“;使用Transaction.Current.DependentClone时

C# “获取异常”;重复交易标识符“;使用Transaction.Current.DependentClone时,c#,multithreading,oracle,transactions,.net-3.5,C#,Multithreading,Oracle,Transactions,.net 3.5,我正在创建一种机制,以便将大量新记录批量插入(导入)到ORACLE数据库中。我正在使用多线程和依赖事务: 创建线程: const int ThreadCount = 4; using (TransactionScope transaction = new TransactionScope()) { List<Thread> threads = new List<Thread>(threadCount); for (int i = 0; i < Thr

我正在创建一种机制,以便将大量新记录批量插入(导入)到ORACLE数据库中。我正在使用多线程和依赖事务:

创建线程:

const int ThreadCount = 4;
using (TransactionScope transaction = new TransactionScope())
{
    List<Thread> threads = new List<Thread>(threadCount);
    for (int i = 0; i < ThreadCount; i++)
    {
        Thread thread = new Thread(WorkerThread);
        thread.Start(Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete));
        threads.Add(thread);
    }
    threads.ForEach(thread => thread.Join());
    transaction.Complete();
}
在此操作过程中,我得到一个类型为
System.Data.OracleClient.OracleException
的异常,消息为
ORA-24757:duplicate transaction identifier


我做错了什么?我是否以错误的方式实现依赖事务?它与Oracle不兼容吗?如果是,是否存在工作区?

我不知道为什么会出现这种异常,但解决方法可能是:

const int ThreadCount = 4;
using (var connection = new OracleConnection(MyConnectionstring))
{
    connection.Open();
    using (var transaction = connection.BeginTransaction())
    {
        List<Thread> threads = new List<Thread>(ThreadCount);
        for (int i = 0; i < ThreadCount; i++)
        {
            Thread thread = new Thread(WorkerThread);
            thread.Start(transaction);
            threads.Add(thread);
        }
        threads.ForEach(thread => thread.Join());

        transaction.Commit();
    }
}

虽然我很欣赏这一努力,但它并没有真正的帮助。由于一个连接不能由多个线程共享,因此该连接将在执行其(非)查询时“锁定”该连接。这导致了一个比单线程环境更慢的解决方案……我更仔细地考虑了您的解决方案。当“准备”部分(如导入、收集数据等)变得越来越大时,它只会越来越快。不是螺纹插入件会加快速度,而是“准备”部分可以在多个螺纹上分离的事实。记录“准备”(并行)后,可以将其写入数据库,在您的情况下,该数据库将成为锁定插入操作的队列。
const int ThreadCount = 4;
using (var connection = new OracleConnection(MyConnectionstring))
{
    connection.Open();
    using (var transaction = connection.BeginTransaction())
    {
        List<Thread> threads = new List<Thread>(ThreadCount);
        for (int i = 0; i < ThreadCount; i++)
        {
            Thread thread = new Thread(WorkerThread);
            thread.Start(transaction);
            threads.Add(thread);
        }
        threads.ForEach(thread => thread.Join());

        transaction.Commit();
    }
}
private void WorkerThread(object transaction)
{
    OracleTransaction trans = (OracleTransaction) transaction;

    using (OracleCommand command = trans.Connection.CreateCommand())
    {
        command.CommandText = "INSERT INTO mytable (x) values (1)  ";
        command.ExecuteNonQuery();
    }
}