在C#中创建新的SqlConnection的开销

6

前段时间,我为我的 .net 应用程序编写了一个 ORM 层,其中所有数据库行都由 DatabaseRecord 的子类表示。有许多方法,如 Load()Save() 等。在我的初始实现中,我在 DatabaseRecord 的构造函数中创建了一个与数据库的连接。

connection = new SqlConnection(
    ConfigurationManager.ConnectionStrings["ConnectionName"].ConnectionString
);

我会在访问数据库的方法开始和结束时,调用Open()Close()来打开和关闭SqlConnection连接。这对于我来说(作为一个熟悉编程但是新手C#和.NET的人)似乎是最有效的方法 - 在类中只有一个连接,并在必要时打开/关闭它。

但是,我最近阅读了一些资料,发现这种模式在很多地方都被推荐使用:

using (var connection = new SqlConnection(...)) {
    connection.Open();
    // Stuff with the connection
    connection.Close();
}

我明白为什么这很理想 - 即使您在中间执行的操作引发未捕获的异常,连接也会自动Dispose()。我只是想知道像这样潜在地多次调用new SqlConnection()的开销是多少。
连接池已经启用,因此我想开销很小,第二种方法应该是最佳实践,但我只是想确保我的假设是正确的。

感谢您提供如此迅速的答案! - vitch
3个回答

8

是的,这是最佳实践。使用using可以使您对Close()的调用具有异常安全性。

创建任何对象的开销确实很小,对于短暂存在于GC第0代的对象来说,开销最小。

请注意,您不再需要在using块的末尾调用Close(),它会自动为您完成(Dispose==Close)。


有多少最小化?是否有任何基准可以显示打开和关闭连接会损失多少性能?当调用Open方法时,是否会进行网络握手? - Christian Findlay
实际上,我认为这篇文章完美地回答了我的问题。https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling - Christian Findlay
如果这篇文章是正确的,连接池应该明确处理握手等操作,并确保没有不必要的握手操作。 - Christian Findlay

1

这部分是个人口味问题。只要使用连接池,创建新连接(或回收池化的连接)的开销将是最小的,因此通常推荐的模式是根据需要创建新的连接对象。

如果您立即运行多个命令,则我认为没有理由为每个命令创建新连接,但应避免长时间保持打开的连接。

此外,您应该注意Dispose方法会为您关闭连接。因此,无需调用CloseDispose。由于using子句在结束时将调用dispose,因此通常不需要调用Close


1
如果您不确定打开/关闭连接的成本,可以将SqlConnection作为类的成员变量,但要使该类IDisposable并在类被释放时处理SqlConnection

其实,我再想一下,我认为这可能是更有效的方法。我在另一个问题中详细阐述了您的建议-如果您能让我知道我是否理解正确,那就太好了: https://dev59.com/RUvSa4cB1Zd3GeqPcS-d - vitch

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