从线程管理实体框架连接



在我的多线程窗口服务中,我在每个线程上打开到db的连接,之后我处理这些连接,尽管问题是当我在系统上执行查询时,一些在db上没有关闭。sysprocesses表。

我运行了两个单元测试,看到了一些奇怪的行为,在第一个单元测试中,我运行了一个有100个任务的循环,在每个任务中我都打开了一个新连接。在这些完成后(我通过WaitAll()看到),我看到一些连接仍然挂在数据库中。在第二个单元测试中,当我在没有并行执行的情况下运行几个open/dispose时,它可以很好地处理它们,并且在我的db中没有挂起连接。

问题是,在我的Windows服务中,这些挂起的连接正在被添加,最终没有更多的地方用于新的连接,数据库对用户来说是不可用的。

下面是代码,第一个是并行的,第二个是不并行的:

    [TestMethod]
    public void TestMultiThreadedAccessToExplicitObjectContext()
    {
        int taskSize = 100;
        List<Task> taskList = new List<Task>();
        int goodSources = 0;
        for (int i = 0; i < taskSize; i++)
        {
            Task newTask = Task.Factory.StartNew(() =>
            {
                System.Data.Objects.ObjectContext objectContext = new PersoniteEntities();
                objectContext.Connection.Open();
                objectContext.Dispose();
                Thread.Sleep(1200);
            });
            taskList.Add(newTask);
        }
        Task.WaitAll(taskList.ToArray());
        GC.Collect();
        total += goodSources;
    }
[TestMethod]
    public void TestMultiThreadedAccessToExplicitObjectContextInline()
    {
        System.Data.Objects.ObjectContext objectContext1 = new PersoniteEntities();
        objectContext1.Connection.Open();
        objectContext1.Dispose();
        System.Data.Objects.ObjectContext objectContext2 = new PersoniteEntities();
        objectContext2.Connection.Open();
        objectContext2.Dispose();
        System.Data.Objects.ObjectContext objectContext3 = new PersoniteEntities();
        objectContext3.Connection.Open();
        objectContext3.Dispose();
        System.Data.Objects.ObjectContext objectContext4 = new PersoniteEntities();
        objectContext4.Connection.Open();
        objectContext4.Dispose();
        System.Data.Objects.ObjectContext objectContext5 = new PersoniteEntities();
        objectContext5.Connection.Open();
        objectContext5.Dispose();
    }

谢谢

使用连接池,每个工作进程(或本例中的线程)都有自己的连接池。因此,如果您将最大池大小设置为3,并生成100个线程,则可能有300个连接。

来自有类似问题的人的更多信息:

ODP。. NET连接池参数

和MS关于连接池如何工作的一些文档,以及连接池碎片的解释:

MSDN - SQL Server连接池(ADO.NET)

解决方案1

在连接字符串

中关闭连接池

MSDN -连接字符串-池

当此键的值被设置为true时,任何新创建的当应用程序关闭连接时,连接将被添加到池中。在下次尝试打开同一连接时,该连接将是从水池里捞出来的。如果连接有,则认为它们是相同的相同的连接字符串。不同的连接有不同的连接字符串。

该键的取值为true、false、yes或no。

例如:

<add 
   name="AppEntities" 
   connectionString="
      metadata=res://*/App_Code.AppModel.csdl|res://*/App_Code.AppModel.ssdl|res://*/App_Code.AppModel.msl;
      provider=System.Data.SqlClient;
      provider connection string=&quot;
         Data Source=.;
         Initial Catalog=Example;
         Integrated Security=True;
         Pooling=False;
         MultipleActiveResultSets=True
      &quot;" 
   providerName="System.Data.EntityClient"
/>

解决方案2

看起来可能有一个涉及信号量的解决方案,详细说明如下:

使用多线程服务的数据库连接池

假设这是您在测试中运行的所有代码,您可能不会查看挂起的连接。这是连接池的正常行为。

当你使用一个线程。net可以重用相同的物理连接,因为它已经从上一个命令关闭。对于多线程,它必须打开几个物理连接来处理并行请求。

p。您应该使用using语句而不是手动. dispose,因为如果open之后的内容抛出异常,则可能会使连接打开的时间比预期的长。因此,您可能会耗尽连接。

最新更新