"打开/关闭"SqlConnection还是保持打开状态?

Ale*_*lex 103 c# sqlconnection

我的业务逻辑是用静态方法在简单的静态类中实现的.这些方法中的每一个在调用时打开/关闭SQL连接:

public static void DoSomething(string something)
{
    using (SqlConnection connection = new SqlConnection("..."))
    {
        connection.Open();

        // ...

        connection.Close();
    }
}
Run Code Online (Sandbox Code Playgroud)

但我认为避免打开和关闭连接可以节省性能.我以前用OleDbConnection类做了一些测试(不确定SqlConnection),它肯定有助于像这样工作(据我记得):

//pass the connection object into the method
public static void DoSomething(string something, SqlConnection connection)
{
    bool openConn = (connection.State == ConnectionState.Open);
    if (!openConn)
    {
        connection.Open();
    }

    // ....

    if (openConn) 
    {
        connection.Close();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以问题是 - 我应该选择方法(a)还是方法(b)?我读了另一个stackoverflow问题,连接池为我保存了性能,我根本不用费心......

PS.它是一个ASP.NET应用程序 - 仅在Web请求期间存在连接.不是win-app或服务.

WeN*_*ers 78

每次使用方法(a).当您开始扩展应用程序时,如果不这样做,处理状态的逻辑将变得非常痛苦.

连接池完成它在锡上所说的内容.只需考虑应用程序扩展时会发生什么,以及手动管理连接打开/关闭状态的难度.连接池可以很好地自动处理它.如果你担心性能会考虑某种内存缓存机制,以免被阻止.


Adr*_*der 75

坚持选择a.

连接池是你的朋友.

  • 恕我直言 - 他甚至不应该做得很近.处置将会这样做. (34认同)
  • @edhedges利用"使用"和关闭()最终只会给新手造成混淆.他们不会理解利用"使用"的目的.不要使用"关闭"而是教他们"使用"的目的.这样他们就可以学得更好,并将他们学到的东西应用到代码的其他部分. (23认同)
  • @RoyiNamir我有点像关闭连接的电话.特别是对于代码库的初学者和新手.它更明确,更易读. (2认同)

Nei*_*ell 28

始终密切的联系,只要你与他们做,所以他们基本的数据库连接可以返回到池中,并可供其他调用.连接池已经过很好的优化,因此没有明显的惩罚.建议基本上与交易相同 - 保持简短并在完成后关闭.

如果你正在使用的代码周围单个事务使用多个连接,在这种情况下,你实际上必须共享连接对象,只有关闭交易一旦完成与运行到MSDTC问题就变得更复杂了.

但是你在这里手工做事,所以你可能想要研究管理连接的工具,比如DataSet,Linq to SQL,Entity Framework或NHibernate.

  • @David Martensson - 当您调用SqlConnection.Open时,实际上并未打开和关闭连接.当连接字符串与先前使用的连接字符串匹配时,ASP.NET将回收池中的活动连接.这涉及的开销是无关紧要的,另外,尝试"自己动手"意味着你必须承担确保连接在每次后续使用时仍然有效的所有管理任务,这增加了复杂性和开销.使用连接池,最佳做法是每次使用时打开和关闭它. (7认同)
  • 在我尊重的情况下,"始终紧密联系"的答案并不适合这个问题......我确实关闭了它们.问题是 - 什么时候. (2认同)

Cri*_*ole 12

免责声明:我知道这已经过时了,但我找到了一个简单的方法来证明这个事实,所以我要投入两分钱.

如果你很难相信汇集真的会更快,那么试试吧:

在某处添加以下内容:

using System.Diagnostics;
public static class TestExtensions
{
    public static void TimedOpen(this SqlConnection conn)
    {
        Stopwatch sw = Stopwatch.StartNew();
        conn.Open();
        Console.WriteLine(sw.Elapsed);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在更换所有通话Open()使用TimedOpen()和运行程序.现在,对于您拥有的每个不同的连接字符串,控制台(输出)窗口将只有一个长时间运行打开,并且会打开一堆非常快的连接.

如果您想标记它们,可以添加new StackTrace(true).GetFrame(1) +到通话中WriteLine.


小智 7

物理连接和逻辑连接之间存在区别.DbConnection是一种逻辑连接,它使用与Oracle的底层物理连接.关闭/打开DbConnection不会影响您的性能,但会使您的代码保持干净和稳定 - 在这种情况下,连接泄漏是不可能的.

此外,您应该记住数据库服务器上并行连接存在限制的情况 - 考虑到这一点,必须使您的连接非常短.

连接池使您免于连接状态检查 - 只需打开,使用并立即关闭它们.