问题:多线程bulkinset
本文关键字:bulkinset 多线程 问题 | 更新日期: 2023-09-27 18:18:28
我尝试用多个线程做一个bulkinsert。在使用linq读取一个数据表(称为'dt')的1000行后,它创建了一个新的数据表并将bulkinsert放入数据库。
下面是初始化线程的代码: 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中出现。OracleBulkCopy类做直接路径加载。如果是这种情况,那么它与多线程应用程序并不真正兼容。在任何时间点,只有一个会话可以对特定对象执行直接路径加载。我认为您可以序列化您的线程,以便在任何时间点只有一个线程具有打开的事务,但这似乎很可能会破坏客户机上多线程的目的。另一方面,由于直接路径插入是加载数据的最有效方式,因此基本上应该能够尽可能快地通过网络加载数据(当然,假设您的数据库可以如此快速地处理数据,但我认为它可以)。