具有依赖注入的连接池是否使用HTTP请求范围?

时间:2012-03-09 21:04:48

标签: ado.net dependency-injection connection-pooling autofac sqlconnection

注意:我不打算使用实体框架,因为它不支持异步查询。

我无法确定哪种方法对于具有依赖注入和SQL连接池的以下方案会更好。 SQL Server Connection Pooling (ADO.NET) MSDN文章建议使用using (sqlConn),因为在启用了连接池的情况下,我connection.Open()connection.Close()不会受到影响。

技术1:

  • SqlConnection依赖项注入我的CustomerRepository类。
  • 为每个HTTP请求使用SqlConnection
  • 的实例
  • 在将connection.Open()注入CustomerRepository类之前调用​​它。

技术2:

  • 仅将连接字符串注入我的CustomerRepository类。
  • 在我的每个CRUD方法中初始化using (SqlConnection)块?

需要考虑的其他事项

  1. 我将使用SqlCommand.BeginExecuteReader()的异步调用进行一些SQL查询,执行大约需要2-4秒。
  2. 在某些特殊情况下,我还需要运行2个或更多并行SQL查询调用。
  3. 请注意这两种技术如何影响IDisposableusing (connection)内容的编码风格。
  4. 问题

    1. 两种方法之间是否有任何差异,因为连接池已启用
    2. 我应该使用哪种技术?为什么?
    3. 技术1的代码示例:

      // ------------------------------------------------------------
      // Autofac Dependency Injection setup
      // ------------------------------------------------------------
      ContainerBuilder builder = new ContainerBuilder();
      builder.Register(
          c => {
              var conn = new SqlConnection( "connectionString" );
              conn.Open(); // open the connection ahead of time before injecting it into my CustomerRepository
              return conn;
          })
          .Named("myNamedConnection", typeof(SqlConnection))
          .InstancePerHttpRequest();
      
      
      builder.Register(
          c => {
              new CustomerRepository(c.ResolveNamed<SqlConnection>("myNamedConnection")))
          })
          .As<ICustomerRepository>();
      
      
      
      // ------------------------------------------------------------
      // CustomerRepository
      // ------------------------------------------------------------
      public class CustomerRepository : ICustomerRepository, IDisposable
      {
          private SqlConnection conn;
          private bool disposed;
          public CustomerRepository(SqlConnection connection)
          {
              conn = connection;
              disposed = false;
          }
      
          public Customer GetById(int id)
          {
              using (var cmd = conn.CreateCommand())
              {
                  // code to retrieve Customer by id
              }
          }
      
      
          public void Dispose()
          {
              Dispose(true);
              GC.SuppressFinalize(this);
          }
      
          protected virtual void Dispose(bool disposing)
          {
              if (!disposed)
              {
                  if (disposing)
                  {
                      if (conn != null)
                      {
                          conn.Dispose();
                          conn = null;
                      }
                  }
      
                  disposed = true;
              }
          }
      }
      

      技术2的代码示例:

      // ------------------------------------------------------------
      // CustomerRepository
      // ------------------------------------------------------------
      public class CustomerRepository : ICustomerRepository
      {
          private readonly string strConn;
          public CustomerRepository(string strConnection) // strConnection has Connection Pooling enabled
          {
              strConn = strConnection;
          }
      
          public Customer GetById(int id)
          {
              using (var conn = new SqlConnection(this.strConn))
              {
                  using (var cmd = conn.CreateCommand())
                  {
                      // code to retrieve Customer by id
                  }
              }
          }
      }
      

      提前感谢任何深思熟虑的投入: - )

1 个答案:

答案 0 :(得分:1)

不要采用技术1.不建议将连接保持打开状态:它应尽快关闭,因此请不要将其打开以便完整请求。

不要采用技术2.在每个存储库中注入连接字符串很麻烦,如果你这样做,我觉得你在代码中缺少抽象。您可能不希望每个存储库自己创建一个新的SqlConnection。

通过向您的存储库中注入某种IDatabase抽象,您可能会更好。您可以在IDatabase实现中注入连接字符串。这种抽象可以有BeginExecuteReader方法,甚至可以有更高级别的抽象。