【问题标题】:Which pattern is better for SqlConnection object?哪种模式更适合 SqlConnection 对象?
【发布时间】:2011-03-23 16:06:55
【问题描述】:

哪种模式更适合SqlConnection 对象?哪个性能更好? 你们提供其他模式吗?

class DataAccess1 : IDisposable
{
    private SqlConnection connection;

    public DataAccess1(string connectionString)
    {
        connection = new SqlConnection(connectionString);
    }

    public void Execute(string query)
    {
        using (SqlCommand command = connection.CreateCommand())
        {
            command.CommandText = query;
            command.CommandType = CommandType.Text;
            // ...

            command.Connection.Open();
            command.ExecuteNonQuery();
            command.Connection.Close();
        }
    }

    public void Dispose()
    {
        connection.Dispose();
    }
}

VS

class DataAccess2 : IDisposable
{
    private string connectionString;

    public DataAccess2(string connectionString)
    {
        this.connectionString = connectionString;
    }

    public void Execute(string query)
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            SqlCommand command = connection.CreateCommand();
            command.CommandText = query;
            command.CommandType = CommandType.Text;
            // ...

            command.Connection.Open();
            command.ExecuteNonQuery();
            command.Connection.Close();
        }
    }

    public void Dispose()
    {            
    }
}

【问题讨论】:

    标签: c# performance sqlconnection sqlcommand


    【解决方案1】:

    没有真正的方法可以回答这个问题。简短而规范的答案是,连接应该在您的工作单元的整个生命周期内保持活跃。因为我们无法知道DataAccess 是如何使用的(它是否在您的应用程序的整个生命周期中都存在,或者您是否实例化它并在您做某事时释放它?),因此无法给出具体答案。

    话虽如此,我会推荐第一种模式,但根据需要实例化并处理您的 DataAccess 对象;不要将其保留超过必要的时间。

    【讨论】:

      【解决方案2】:

      建议使用DataAccess2。不过这是个人喜好。有些人甚至可能建议你的班级是static。很难说一个比另一个性能更好。你在IDisposable 的道路上,这很棒。

      我很乐意阅读并维护您问题中显示的上述两种样式。

      考虑让您的 DAL 也能够从 .config 读取连接字符串,而不是只允许在构造函数中传递值。

      public DataAccess2(string connStr)
      {
          this.connectionString = connStr;
      }
      public DataAccess2()
      {
          this.connectionString = 
                  ConfigurationManager.ConnectionStrings["foo"].ConnectionString;
      }
      

      考虑将 SqlCommand 也包含在 using 中。

      using (var conn = new SqlConnection(connectionString))
      {
          using(var cmd = conn.CreateCommand())
          {
      
          }
      }
      

      【讨论】:

      • 我建议反对让班级读取连接字符串。让应用程序读取配置信息并传递给消费者;没有理由限制类的可移植性。
      • @Adam:关于便携性的限制,我同意你的看法。我将修改以包含一个允许调用者提供值的 ctor。
      【解决方案3】:

      我认为这取决于您的 DataAccess 对象打算如何使用,如果它在“using”子句中使用,那么连接保证在完成后被释放。

      但总的来说,我更喜欢第二种模式,因为 sql 连接是在 Execute 方法中创建和处置的,因此当您忘记处置 DataAccess 对象时,它不太可能保持打开状态。

      考虑到 sql 连接可能是一种稀缺资源,我认为应该尽一切努力确保它们不会被浪费。

      【讨论】:

        【解决方案4】:

        如果您进行并发调用,第一个将导致错误。 第二个将确保您为每个命令使用干净的连接,从而产生更多的连接。

        我同意上面的陈述,它取决于使用的场景,为了解决与第一个相关的问题,我有一个需要使用这种模式的包装器,所以我设置了一个字段值 boolean 来显示一个命令已在连接上执行,然后“排队”执行下一个命令。

        当然,在某些情况下您可能更喜欢使用多个连接...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-29
          • 2011-02-27
          • 1970-01-01
          • 2023-03-10
          • 1970-01-01
          • 1970-01-01
          • 2017-04-11
          相关资源
          最近更新 更多