2014-02-20 29 views
0

我在一个很长的运行服务中有一个非常小的数据抽象类。它是一个静态类,作为一个跨类实用程序被称为无状态(就像DataTable someResults = Data.SelectFooFromBar()) - 我不想在几个离散和无关的类中实例化它。该服务在出现时会提供Data.Initialize(connectionString)。该Initialize样子:长时间维护.NET OdbcConnection对象

private static string connectionString; 
private static OdbcConnection connection; 

public static void Initialize(string mySqlConnectionString) 
{ 
    /*mySqlConnectionString would look something like this: 
    "Provider=MSDASQL; 
     Driver={MySQL ODBC 3.51 Driver}; 
     UID=some_db_user; 
     PWD=some_db_pass; 
     Server=db-host; 
     Port=3306; 
     Database=some_db; 
     Protocol=TCP; 
     Compress=false; 
     Pooling=true; 
     Min Pool Size=0; 
     Max Pool Size=100; 
     Connection Lifetime=0; 
     OPTION=16386;"*/ 

    //Ensure only one connection exists to prevent leaks, and also 
    // only modify the connection if the connection string has changed: 
    if (connection == null || connectionString != mySqlConnectionString) 
    { 
     connectionString = mySqlConnectionString; 
     connection = new OdbcConnection(connectionString); 
    } 
} 

这里是实际进行消毒和执行查询面向公众的方法所使用的方法:

private static DataTable Select(string query) 
{ 
    try 
    { 
     query = Sanitize(query); 

     connection.Open(); 
     DataTable dt = new DataTable(); 
     OdbcDataAdapter da = new OdbcDataAdapter(query, connection); 
     da.Fill(dt); 
     connection.Close(); 

     return dt; 
    } 
    catch (Exception ex) 
    { 
     connection.Close(); 
     ExceptionHandler(ex, query); 
     return null; 
    } 
} 

最后一个实际的面向公众的数据的方法:

public static DataTable SelectFooFromBar() 
{ 
    return Select("SELECT foo FROM bar"); 
} 

我的问题是确保我的connection对象总是好的最好方法是什么?

  • 是否有可以处理的事件或连接不良时发生了什么?
  • 每次查询运行时打开/关闭connection对象也有好还是坏的?
  • 我应该有多个catches,所以我可以说,做一个connection.Close()就当它是一个查询级别的错误移动,但到connection = new OdbcConnection(connectionString)时,我异常指示给我,我是断开的(不知道这是哪个异常)

    它离开它似乎不好打开所有的时间,但我想获得第二个意见。

+1

使用'using'语句。 – SLaks

+1

进行静态连接是一个非常糟糕的主意。 – SLaks

+1

使用参数。 – SLaks

回答

2

您应该为每个操作打开一个新的连接,而不是打开一个连接并重新使用它。

在幕后,实际的数据库适配器将有一个连接池。当请求新连接时,它保持打开并分配的多个连接。通常创建一个新的连接是很昂贵的,但是由于连接池的原因,这个开销在短时间内创建很多连接时根本没有感觉到。

如果你的连接连接失败会抛出(当然,你要确保连接池在你的数据库配置中启用了,但你表现出什么基础,这显然已经是了。)

一个例外。让这个例外泡沫到可以适当处理这种情况的地方。这几乎肯定不是您的DAL,而是您的业务逻辑,在某种程度上,可以通知用户错误并确定应该做些什么。

+0

你提到这很有趣,因为那正是它以前的样子。问题在于Data类不断处理大量调用,因此它会生成数千个TIME_WAIT连接,而这些连接占用了大量必须维持连接状态的网络基础结构上的大量资源。所以我决定尝试只用一个连接来消除这个问题。 – kmarks2

+1

@ kmarks2如果您没有足够的资源来支持那么多的话,请将您池中的最大连接数降低到一个更易于管理的数字。 – Servy

+0

我想我会恢复到之前的样子(每个操作的新连接),并且会大大降低线程池大小。 Servy的建议非常感谢。 – kmarks2

0

如果您未使用连接池,请创建一个返回打开连接的函数GetConnection。在此函数内部,测试全局连接对象是否为空或关闭。如果是这样,请重新打开它。连接关闭并不重要,重要的是它在需要时打开。

+0

我使用的连接池。最小= 0,最大= 100。 – kmarks2

+1

您仍然需要处理多个线程同时调用DAL的任何方法 – Servy

+1

在这种情况下,池正在为您完成大部分工作,在释放它时并不真正关闭连接,它会返回到池中以供重用 –

1

你不应该一直打开它。你将不得不写更多的代码,以监视连接的状态和处理超时的情况下,网络连接问题等长期运行的开放连接。

你会注意到大多数人在使用中包装连接。根据需要建立连接没有太多的成本。

+1

因此您在说创建一个新的连接,打开它,对其进行操作并在每次查询需要处理时关闭它? – kmarks2