【问题标题】:Connection Pooling w/ Dependency Injection Use HTTP Request Scope or Not?使用依赖注入的连接池是否使用 HTTP 请求范围?
【发布时间】:2012-03-09 21:04:48
【问题描述】:

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

我无法确定哪种方法更适合以下使用依赖注入和 SQL 连接池的场景。 SQL Server Connection Pooling (ADO.NET) MSDN 文章建议使用 using (sqlConn),因为我不会在启用连接池的情况下对 connection.Open()connection.Close() 进行打击。

技巧一:

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

技巧2:

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

需要考虑的其他事项

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

问题

  1. 鉴于 连接池 已启用,这两种方法之间是否有任何区别?
  2. 我应该使用哪种技术以及为什么?

技术 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
            }
        }
    }
}

在此先感谢您提供周到的意见 :-)

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 我同意注入连接字符串可能很麻烦。
    • 它也违反了 DRY 原则。使用将连接字符串公开为属性的IDatabase 抽象绝对是一种更好的方法。谢谢你的好建议和回答。
    • 我不会将连接字符串作为属性公开,因为这意味着存储库仍会创建连接。管理连接将是 IDatabase 抽象的一项工作。
    猜你喜欢
    • 2017-04-25
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多