并行执行存储过程.fore .net

时间:2015-12-11 13:35:56

标签: c# .net multithreading linq parallel.foreach

我需要运行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
}
});

2 个答案:

答案 0 :(得分:2)

System.Data.Linq.DataContext类不是线程安全的。

参考:https://msdn.microsoft.com/en-us/library/system.data.linq.datacontext(v=vs.110).aspx

  

此类型的任何公共静态成员都是线程安全的。不保证任何实例成员都是线程安全的。

这就是为什么你必须在DataContext循环中创建ForEach的新实例的原因。

此外,我还要考虑专为处理数千个插页而设计的SqlBulkCopyhttps://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
}
});