注入连接字符串 vs IDbConnection

4
注入连接字符串与注入IDbConnection实例之间的权衡是什么?
我使用StructureMap将各种服务注入到我的ASP.NET MVC应用程序中,其中大部分需要访问数据库以进行LINQ-to-SQL查询。注入IDbConnection似乎比通用连接string参数更易于测试和配置IoC,但我担心如果我没有明确地将连接包装在using块中,那么开放的连接会挂起。
我应该注意哪些连接池优缺点?

注入的连接字符串

using (var con = new SqlConnection(InjectedConnectionString))
{
    con.Execute("INSERT INTO Logs (...) VALUES (...)");
    using (var db = new MyDataContext(con))
    {
        var records = from p in db.Products
                      select p;
    }
}

Injected IDbConnection

con.Execute("INSERT INTO Logs (...) VALUES (...)");
using (var db = new MyDataContext(InjectedConnection))
{
    var records = from p in db.Products
                  select p;
}

为什么你应该关注开放连接?因为你正在使用 using 块,它确保连接始终会被关闭。 - Dai
@David,只有当我注入连接字符串并显式使用using时才会发生。当注入IDbConnection时,我不需要这样做,这就是区别的一部分。我会在问题中表达得更清楚。 - Petrus Theron
啊,我明白了。在注入IDbConnection的情况下,DataContext不会处理你的连接的释放(它只会在自己从连接字符串创建连接时处理连接的释放),所以这是你的责任。但是使用连接池技术,连接是很便宜的,所以个人建议注入连接字符串并避免连接重用(除非你使用的数据库系统不使用连接池技术)。 - Dai
1个回答

3
任何一个相对复杂的IoC容器(例如structuremap)的特性之一是能够控制对象的生命周期。默认情况下,structuremap使用瞬态生命周期。这意味着它为每个对象图创建一个新实例。在实践中,这通常与每个Web请求相同(除非您在代码中添加了container.GetInstance<T>()的用法)。
通过使用structuremap来注入像数据库连接这样的珍贵资源,您可以控制它们存在的时间。单个资源可以(如果您选择)在整个Web请求期间重复使用,或者每次使用时都创建新的资源。
此外,这些选择(以及配置)现在已经被外部化到注册表中,而不是散落在您的代码中。如果您必须更改连接的创建方式,只需查看一个地方即可。具有单一职责的类始终是首选。
就您的连接池问题而言,没有任何IoC容器会涉及连接池等详细信息。但是它们可以帮助管理对象的生命周期。Structuremap将在任何IDisposable对象上调用Dispose()方法(实际上是解释器调用)。对于每个生命周期,都有自己的规则来确定何时和如何处理对象的释放。瞬态生命周期依赖于CLR进行处理,然而HttpRequestScoped会在每个请求结束时确定性地处理对象的释放。使用HttpRequestScoped可以避免连接数达到最大值。

如果StructureMap注入了多个IDbConnection实例(不确定何时会发生),如果它们没有及时释放,连接池是否会达到最大值? - Petrus Theron
我对连接池或Linq-to-SQL并不是专家,但请看一下我的最新编辑。 - kelloti
谢谢,kelloti。HybridHttpOrThreadLocalScoped是否对于Web应用程序等同于HttpRequestScoped - Petrus Theron
一个事后的想法 - 你实际上无法防止连接池达到最大值,除非你在 Web 请求之间共享连接。但是使用 HttpRequestScope 可以通过确定性地处理连接来减少这种可能性。 - kelloti
有点像,名字就说明了一切。在生产中,是的,它们是等效的。在单元测试中,它将使用ThreadLocal,因为没有HTTP上下文。 - kelloti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接