我需要运行4个存储过程并根据收到的数据创建查询。 q容器中有大约5k项目,存储过程执行20k。我使用LINQ连接到DB并执行它们,它在正常的foreach循环中工作得很好但是有一个问题:代码大约需要一个小时才能完成。这是很长的路,所以我试着编写Parrarel.ForEach而不是普通的ForEach循环。代码在几次迭代后崩溃 - 我猜LINQ连接只是没有使用Parrarel。任何想法如何在多个线程中运行LINQ存储过程?
var dataCollector = new EpmDataCollector();
Parallel.ForEach(q, history =>
{
try
{
var queriesBefore = dataCollector.GetQueries().Count;
var weight = dataCollector.CreateProjectQuery(history);//function executes stored procedure and creates queries from data received, then adds them to container (ConcurrentBag) in dataCollector
dataCollector.CreateHoursQuery(history);//like above
dataCollector.CreateCostQuery(history);//same
dataCollector.CreateIncomeQuery(history);//same
var log = ...
Global.log.Info(log);
//i++;
Interlocked.Increment(ref i);
if (i % 10 == 0)
{
//calculate and log estimation time
}
}
catch (Exception ex)
{
//catch code
}
});
答案 0 :(得分:2)
System.Data.Linq.DataContext
类不是线程安全的。
参考:https://msdn.microsoft.com/en-us/library/system.data.linq.datacontext(v=vs.110).aspx
此类型的任何公共静态成员都是线程安全的。不保证任何实例成员都是线程安全的。
这就是为什么你必须在DataContext
循环中创建ForEach
的新实例的原因。
此外,我还要考虑专为处理数千个插页而设计的SqlBulkCopy
(https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=vs.110).aspx)。
答案 1 :(得分:0)
将EpmDataCollector的创建移动到循环中,如下所示:
Parallel.ForEach(q, history =>
{
try
{
var dataCollector = new EpmDataCollector();
var queriesBefore = dataCollector.GetQueries().Count;
var weight = dataCollector.CreateProjectQuery(history);//function executes stored procedure and creates queries from data received, then adds them to container (ConcurrentBag) in dataCollector
dataCollector.CreateHoursQuery(history);//like above
dataCollector.CreateCostQuery(history);//same
dataCollector.CreateIncomeQuery(history);//same
var log = ...
Global.log.Info(log);
//i++;
Interlocked.Increment(ref i);
if (i % 10 == 0)
{
//calculate and log estimation time
}
}
catch (Exception ex)
{
//catch code
}
});