【问题标题】:How to protect SqlDataReader from multiple access in C#如何在 C# 中保护 SqlDataReader 免受多次访问
【发布时间】:2012-05-01 08:22:29
【问题描述】:

我有一个用 C# 编写的多线程 TCP 服务器软件。许多线程应该从数据库中读取,我正在使用 SqlDataReader 从数据库中读取。当一个线程想要从数据库中读取时,没有问题,但是当两个或更多线程想要从数据库中读取时,这种情况就开始出现问题了。 .NET 给出了这个例外:已经有一个打开的 DataReader 与此命令关联,必须先关闭它。

如何防止错误发生?如何保护 SqlDataReader 免受多次访问?互斥锁适合这个问题吗?

【问题讨论】:

  • 为什么不同的线程共享一个连接?
  • 作为旁注,还有一个叫做“多个活动结果集”(MARS)的东西 - 但是,我只是为了完整性而提到这一点:更好的答案是“不共享连接”

标签: c# multithreading sqldatareader


【解决方案1】:

如何保护 SqlDataReader 免受多次访问?

甚至不共享连接。

为每个数据库操作创建一个新的SqlConnection(在using 语句中以在操作结束时将其释放),并让连接池处理以提高效率。

如果您不共享连接,则不会出现此错误,也不会通过锁定序列化您的数据库访问。

【讨论】:

    【解决方案2】:

    您应该向 .net 运行时询问每个线程内的新 sql 连接。就速度而言,这是最佳解决方案(它使用 .net 的 sql 连接池,因此您不会浪费时间建立连接)。

    【讨论】:

    • 这里重要的是连接,而不是阅读器
    【解决方案3】:

    我建议每个请求创建一个新连接,而不是尝试重新使用现有的活动连接。我假设您正在使用某种类成员或对连接的静态引用,而不是将其设置为方法范围:

    private void RespondingToTcpRequest()
    {
        using (var connection = new SqlConnection(""))
        using (var command = new SqlCommand("", connection))
        {
             connection.Open();
    
             using (var reader = command.ExecuteReader())
             {
                 // No locks or sharing issues here!
             }
        }
    }
    

    如果我有一些示例代码来演示您目前拥有的内容,我可以根据您的情况调整该想法。

    至于锁定,如果你真的想沿着这条路走(说真的,不要),你需要做的就是锁定(基本的同步原语):

    private static readonly object ReaderLock = new object();
    
    private void RespondingToTcpRequest()
    {
        lock (ReaderLock)
        {
            // database connection, command, reader stuff here.
        }
    }
    

    不一定需要互斥锁,因为问题是进程本地的,lock 关键字就足够了。再说一遍,说真的,不要

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      相关资源
      最近更新 更多