C# EXECUTESQLCOMAND并行执行
SQL Server 11.0.3、C#.NET 4.5、WCF、EF v4.0.30319 我有下表存储查询: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
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;
}