c# - 问题: Multithread bulkinsert

标签 c# multithreading oracle bulkinsert

我尝试使用多个线程进行批量插入。使用 linq 读取一个数据表(称为“dt”)的 1000 行后,它创建了一个新的数据表并将批量插入到数据库中。

有初始化线程的代码:

        ManualResetEvent[] doneEvents = new ManualResetEvent[10];
        BancoDAO[] fibArray = new BancoDAO[10];

         for (int i = 0; i < 10; i++)
        {
            doneEvents[i] = new ManualResetEvent(false);
            BancoDAO bd = new BancoDAO() 
            {
                _doneEvent = doneEvents[i],
                dataTable = (dt.AsEnumerable()
                    .Skip(i * 1000)
                    .Take(1000)
                    ).CopyToDataTable<DataRow>() 
            };
            fibArray[i] = bd;
            ThreadPool.QueueUserWorkItem(bd.ThreadPoolCallback, i);
        }

        WaitHandle.WaitAll(doneEvents);

如您所见,插入发生在 BancoDAO 类上。这是代码:

    public DataTable dataTable = new DataTable();
    public ManualResetEvent _doneEvent;

    public void ThreadPoolCallback(Object threadContext)
    {
        int threadIndex = (int)threadContext;
        GravaTabelaThread(dataTable);
        _doneEvent.Set();
    }

    public static void GravaTabelaThread(DataTable dt)
    {
            OracleConnection cteste = new OracleConnection(ConfigurationManager.ConnectionStrings["TesteUpload"].ToString());
            cteste.Open();
            OracleBulkCopy bcp = new OracleBulkCopy(cteste);
            bcp.DestinationTableName = "MAG_T_SORTIMENTO2";

            foreach (KeyValuePair<string, string> k in ColumnMappings())
            {
                bcp.ColumnMappings.Add(k.Key, k.Value);
            }
            try
            {
                bcp.WriteToServer(dt);
                bcp.Dispose();
            }
            catch (Exception ex)
            {
            }
            cteste.Close();
            //Now I open and close the connection everytime after doing the bulkinsert in the database.
            //I'm not using anymore the same connection.
    }

问题是:某些线程将值插入数据库...有时会发生此异常(我会将 oracle 消息从葡萄牙语翻译成英语,所以,请记住这是“免费翻译”):

{Oracle.DataAccess.Client.OracleException Error in row '1' column '1'
ORA-39776:  API fatal error, wrong directoty way when loading the table USR_TRANSF.MAG_T_SORTIMENTO2
ORA-39781: Loads of direct path stream are not allowed after another context loading the same table was to be terminated  in Oracle.DataAccess.Client.OracleBulkCopy.PerformBulkCopy()
   in Oracle.DataAccess.Client.OracleBulkCopy.WriteDataSourceToServer()
   in Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table, DataRowState rowState)
   in Oracle.DataAccess.Client.OracleBulkCopy.WriteToServer(DataTable table)
   in UploadArquivo.BancoDAO.GravaTabelaThread(DataTable dt) at c:\Users\Rafael.pinho\Desktop\UploadArquivo\UploadArquivo\UploadArquivo\BancoDAO.cs:linha 49}

最佳答案

从 ODP.Net 开发人员指南中可以看出 OracleBulkCopy class does a direct-path load 。如果是这样的话,那么它与多线程应用程序并不真正兼容。在任何时间点,只有一个 session 可以对特定对象执行直接路径加载。我想您可以序列化您的线程,以便在任何时间点只有一个线程具有打开的事务,但这似乎很可能会破坏客户端上多线程的目的。另一方面,由于直接路径插入是加载数据的最有效方式,因此您基本上应该能够像通过网络泵送数据一样快地加载数据(当然,假设您的数据库可以快速处理数据)但我认为可以)。

关于c# - 问题: Multithread bulkinsert,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17088979/

相关文章:

c# - 使用包含的 Linq 查询不起作用

java - 如何从后台线程调用 Java 类

c# - Parallel.ForEach 和 ConcurrentDictionary 比常规字典慢

sql - Oracle 和 group by 的奇怪行为

mysql - 从oracle导入数据到mysql

c# - C# 中的德语字母和编码

c# - SQLCE - Upsert(更新或插入) - 如何使用常用方法准备一行?

c# - 如何将适配器模式应用于集合?

java - MQ 与 REST 多线程性能对比

View 与新表的数据库性能