C# EXECUTESQLCOMAND并行执行

C# EXECUTESQLCOMAND并行执行,c#,sql-server,linq,entity-framework,parallel.foreach,C#,Sql Server,Linq,Entity Framework,Parallel.foreach,SQL Server 11.0.3、C#.NET 4.5、WCF、EF v4.0.30319 我有下表存储查询: OBJECT_TYPE OBJECT_NAME OBJECT_TYPE_NAME OBJECT_QUERY 1 HUB_PERSON HUB MERGE INTO ... 1 HUB_GPS HUB

SQL Server 11.0.3、C#.NET 4.5、WCF、EF v4.0.30319

我有下表存储查询:

OBJECT_TYPE     OBJECT_NAME         OBJECT_TYPE_NAME    OBJECT_QUERY
1               HUB_PERSON          HUB                 MERGE INTO ...
1               HUB_GPS             HUB                 MERGE INTO ...
2               LNK_PERSON_GPS      LNK                 MERGE INTO ...
2               SAT_CURR_PERSON     SAT                 MERGE INTO ...
2               SAT_GPS             SAT                 MERGE INTO ...
2               SAT_HIST_PERSON     SAT                 MERGE INTO ...
我必须按照
OBJECT\u TYPE
列指定的顺序从我的服务执行查询。具有相同
OBJECT\u TYPE
的查询可以按任何顺序执行,这就是我希望在可能的情况下并行执行这些查询的原因

以下是我当前使用的函数,没有并行性:

public int ExecuteLoadSources()
        {
            int nb = 0;
            using (POCDVEntities POCDb = new POCDVEntities())
            {
                using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required))
                {
                    IEnumerable<string> res = (
                        from a in POCDb.LOADING_SOURCE_QUERY
                        orderby a.OBJECT_TYPE
                        select a.OBJECT_SQLSRV_QUERY
                    );
                    foreach (string req in res)
                    {
                        POCDb.Database.ExecuteSqlCommand(req);
                    }
                    nb = POCDb.SaveChanges();
                    transaction.Complete();
                }
            }
            return nb;
        }
第一次运行该函数时,我得到的
基础提供程序在打开时失败。
,然后我再次尝试获取
超时。操作完成前超时或服务器没有响应。

我做得对吗?
有什么建议吗?

我可以对此给出一个抽象的答案,它可能不会直接回答您的问题(我也没有代表发表评论),但对于这类问题,它仍然是有价值的信息

您尝试执行的操作存在一些问题

第一个是数据库上下文(扩展为sql连接)和线程并发性。您绝对不能跨线程共享连接,必须在每个线程上创建一个新连接,因为它是并行生成的。由于连接池的存在,这实际上不是一个bug交易,因此您的性能损失是最小的。因此,在您的情况下,需要在并发块内创建上下文实例

第二,在事务内部的数据库上执行并行查询通常不是一个好的策略。原因是,在同一数据库上同时运行多个查询时,需要注意隔离模式。根据连接和全局设置,您可能会敲打日志/日志并调用DTC。如果您的整个查询集作为一个整体必须是事务安全的,那么并行运行查询对您没有任何好处,而应该按顺序运行每个查询。如果只有每个查询必须是事务安全的,那么应该在并发块中创建事务上下文

最后一个建议是使用
任务
而不是
并行
。拥有可以并行运行的嵌套任务结构比在循环中执行并行并发块更有组织意义。在这种情况下,您将有一个主任务(您可以
等待()
打开),每个
对象类型都有子任务。通过在查询数据集上迭代
GroupBy
查询,可以生成
任务
结构。不过,正如前面所说,这只是一个建议,并不是实现查询并行执行所必需的


另一个要考虑的问题(类似于<代码>任务>代码>策略),是使用异步方法来执行每个查询,然后使用一个简单函数调用每个异步方法,并在最后等待所有的方法。我只是想一想。

我不认为一个
SqlConnection
可以从多个线程同时使用,即使使用MARS也是如此。而那
并行。ForEach
将把
ExecuteSqlCommand
放在另一个线程上,这可能会使
TransactionScope
无用。好吧,所以我可以假设这是不可能的?
public int ExecuteLoadSources()
        {
            int nb = 0;
            using (POCDVEntities POCDb = new POCDVEntities())
            {
                using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required))
                {
                    IEnumerable<string> res = (
                        from a in POCDb.LOADING_SOURCE_QUERY
                        select a.OBJECT_SQLSRV_QUERY
                    );
                    int maxValue = (from a in POCDb.LOADING_SOURCE_QUERY select a.OBJECT_TYPE).Max();
                    for (int i = 1; i <= maxValue; i++)
                    {
                        IEnumerable<string> res2 = (
                            from a in POCDb.LOADING_SOURCE_QUERY
                            where a.OBJECT_TYPE == i
                            select a.OBJECT_SQLSRV_QUERY
                        ).ToList();
                        Parallel.ForEach(res2, req2 =>
                        {
                            POCDb.Database.ExecuteSqlCommand(req2);
                        });
                    }
                    nb = POCDb.SaveChanges();
                    transaction.Complete();
                }
            }
            return nb;
        }