【问题标题】:.NET, the SqlConnection object, and multi-threading.NET、SqlConnection 对象和多线程
【发布时间】:2014-05-30 04:54:56
【问题描述】:

我们有一个使用 SQL Server 2008 R2 数据库的应用程序。在应用程序中,使用SqlConnection 对象调用数据库。

这个SqlConnection 对象被初始化一次,第一次被访问,然后在整个应用程序中重新使用。我们使用的操作如下:

Protected _cn As SqlConnection = Nothing

...

Protected Sub Open()
    If _cn Is Nothing Then
        _cn = New SqlConnection(_sqlConn)
    End If

    If _cn.State = ConnectionState.Closed OrElse _cn.State = ConnectionState.Broken Then
        _cn.Open()
    End If
End Sub

这在程序的正常执行期间工作得非常好。但是,应用程序的某些部分以多线程方式执行。当执行这些部分之一时,如果执行其他操作,则会经常发生错误。

经过一番挖掘,我意识到这是因为有时两个不同的线程都试图使用同一个 SqlConnection 对象。

所以,在确定了问题之后,我现在需要找到解决方案。显而易见的解决方案是在每次数据库调用需要一个对象时重新创建SqlConnection 对象——在这种情况下,它永远不会被共享。有什么理由这样做吗?出于性能原因,我最初假设应用程序的每个会话只有一个连接对象,但实际上是这样吗?

如果我们确实需要只打开一个连接对象,建议的解决方案是什么?我应该设置某种计时器,它会一直循环直到连接对象可用,然后访问它?

【问题讨论】:

  • 如果线程的性质是它多次调用数据库然后线程关闭,您可能希望在线程中保持连接打开并用线程关闭它。确保不要跨线程共享连接。

标签: .net sql-server multithreading connection-pooling


【解决方案1】:

显而易见的解决方案是每次数据库调用需要一个 SqlConnection 对象时重新创建它——在这种情况下,它永远不会被共享。有什么理由不这样做吗?

相反,这绝对是你应该做的。这就是SqlConnection 的行为设计。您应该使用Using 语句在您使用它的块的末尾自动关闭连接,连接池机制将自动处理与数据库的真正底层连接。

【讨论】:

  • 只是想知道,如果您需要两个线程的更改才能进入同一个事务,该怎么办?您不必“共享”连接吗?
  • @MoslemBenDhaou:我认为如果你有两个线程想要在同一个事务中做某事,那么无论如何你都会遇到大问题。您将必须在它们之间进行协调——否则您将如何知道何时提交?在这一点上,将操作放在某个生产者/消费者队列中以在一个线程中完成整个事务可能会更好。
  • 好吧,我有一个 FileShare 爬虫(获取权限并将它们放到某个地方以供以后审核)。目前它正在启动多个线程来爬取同一个文件夹(以加快进程)。我希望在同一个事务中提交每个文件夹,而不是进行不完整的扫描(当前情况,当某些线程失败时)。目前没有实施交易概念,但我正在评估这些选项。生产者/消费者队列将是一个选项,但不幸的是内存是一个限制。我想我被记忆/时间妥协所困扰。还有其他建议吗?
  • @MoslemBenDhaou:听起来你正试图在一个完全不同的问题的 cmets 中提出一个新问题。我建议你问一个完全不同的问题。
  • 在我的例子中,在实施 Jon 的方法后,我的应用程序从大约四分之一的线程超时并且每个周期花费约 1 分钟,到一切顺利并在一两秒内完成.谢谢乔恩!
【解决方案2】:

我认为没有理由不在每次需要时都创建 SQL 连接。事实上,这可能是最好的方法,因为它为 .NET 框架提供了最有效地管理和重用连接的灵活性。将每个 SQL 连接包装在 USING 中,以便尽可能短地挂起它们。

我们创建了一个创建连接的方法,每个人都使用它:

using (var conn = GetConnection())
    using (var proc = GetProcedure(conn, "procname"))
        using (var reader = proc.GetReader())
        {
            ... DB stuff
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2016-09-30
    • 1970-01-01
    相关资源
    最近更新 更多