Parallel.Foreach循环创建多个数据库连接会引发连接错误?

时间:2012-07-07 17:04:06

标签: c# sql entity-framework task-parallel-library

“登录失败”错误从未重新出现,好奇吗?然而,其他连接错误似乎是通过砰击服务器来解释的。错误发生的随机性仍然是一个谜。

  

登录失败。登录来自不受信任的域,不能与Windows身份验证一起使用

我想让我的代码并行运行,所以我将foreach循环更改为并行的foreach循环。这似乎很简单。每个循环连接到数据库,查找一些东西,执行一些逻辑,添加一些东西,关闭连接。但我得到了上述错误?

我正在使用我的本地sql server和实体框架(每个循环使用它自己的上下文)。连接多次使用相同的本地登录或其他什么问题?我是怎么解决这个问题的?

我(在尝试转换到parallel.foreach循环之前)将我正在循环的对象列表拆分为四个组(单独的csv文件)并运行我的程序的四个并发实例(总体运行速度比只有一个,因此并行的想法)。所以似乎连接到db应该不是问题吗?

有什么想法吗?

修改: 这是之前的

var gtgGenerator = new CustomGtgGenerator();
var connectionString = ConfigurationManager.ConnectionStrings["BioEntities"].ConnectionString;

var allAccessionsFromObs = _GetAccessionListFromDataFiles(collectionId);

ForEach(cloneIdAndAccessions in allAccessionsFromObs)
    DoWork(gtgGenerator, taxonId, organismId, cloneIdAndAccessions, connectionString));

var gtgGenerator = new CustomGtgGenerator();
var connectionString = ConfigurationManager.ConnectionStrings["BioEntities"].ConnectionString;

var allAccessionsFromObs = _GetAccessionListFromDataFiles(collectionId);

Parallel.ForEach(allAccessionsFromObs, cloneIdAndAccessions => DoWork(gtgGenerator, taxonId, organismId, cloneIdAndAccessions, connectionString));

在DoWork内部,我使用BioEntities

using (var bioEntities = new BioEntities(connectionString)) {...}

它变得古怪和古怪......

我在DoWork方法中添加了一些代码:

Debug.WriteLine(“Executing “ + itemName + ” as “ + WindowsIdentity.GetCurrent().Name);

它神秘地开始工作(实际上非​​常好/快)。但最终我得到了同样的例外(大约一个小时后)。但我能够追踪到这个......?

A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll

EDIT2: 嗯..我今天早上来上班并解雇了它(痴迷于理解为什么它会起作用一点点)并且到目前为止它正在顺利地工作(并且快速!)。偶尔:线程''(0x27c8)已退出,代码为0(0x0)。 线程''(0x26b8)已退出,代码为0(0x0)。

但除此之外还没有弄乱呢?坦率地说,这让我更加担心。这是一次性的事情,所以我可以使用它(如果它有效),但是发生了什么?它可能是NLOG,登录多线程clogs东西并导致sql超时?我真的不明白。一旦它再次停止工作,我会试着解决问题。有没有办法重置sql服务器,我不知道为什么它会工作一个小时,然后搞砸了,然后再工作超过几秒钟,现在(重启后)工作(约30分钟)至今)?

2 个答案:

答案 0 :(得分:2)

您的身份不会流向执行并行for.each基础任务的工作线程。

这里的答案很好,所以我不会复制它。 TPL Task in WCF service fails to use correct IIS security Credentials (SQL Connection)

答案 1 :(得分:0)

很抱歉回答我自己的问题,但有时某个地方可能对某人有价值。

添加(并随后删除)以下代码以查看每个线程使用的标识时,“登录失败”错误再也不会发生。我不确定使用它是否会影响某些东西,但我现在不使用它,它似乎永远不会在最初给出的链接和答案中讨论身份问题。

Debug.WriteLine("Executing " + cloneIdAndAccessions.Item1.ToString() + " as " + WindowsIdentity.GetCurrent().Name);

这里肯定存在两个问题,第一个是屏蔽后者。 但我仍然遇到以下两种类型的连接错误。特别是(我注意到)在打开SQL Server Management Studio之后,可能会使服务器紧张。

System.Data.EntityCommandExecutionException: An error occurred while reading from the store provider's data reader. See the inner exception for details. ---> System.Data.SqlClient.SqlException: The query processor could not start the necessary thread resources for parallel query execution.

和...

System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

所以,我的解决方案(因为我无法找到押韵也不会出现错误)是简单地捕获错误并记录Parallel.ForEach循环中的哪个对象抛出它,然后重新运行这些对象。仍然比简单的foreach循环快得多。

编辑:嗯,这很有趣,我发现了一些押韵/错误的原因(不是当它们被抛出但也许是为什么)。如果我将Parallel.ForEach循环中的对象数量分成较小的(10,000个对象而不是100,000个)组,那么我就不会抛出任何异常。 NICE。

所以摘要 - 检查身份,然后可能会破坏你在foreach循环中运行的组...并且有人弄清楚为什么这是必要的并报告回来:)

编辑/结束

与深入研究任务和线程疯狂相比,这不是最好的解决方案,但相对简单。