C#数据库包装器设计

时间:2010-08-24 05:52:02

标签: c# database wrapper design-patterns

我正在为C#设计数据库包装器。 以下是我的两个选项:

选项A:

class DBWrapper:IDisposable
{
     private SqlConnection sqlConn;

     public DBWrapper()
     {
            sqlConn = new SqlConnection("my connection string");
            sqlConn.Open();
     }

     public DataTable RunQuery(string Sql)
     {
              implementation......
     }

     public Dispose()
     {
            if(sqlConn != null)
                   sqlConn.Close();
     }
}

选项B:

class DBWrapper
{
     public DBWrapper()
     {            
     }

     public DataTable RunQuery(string Sql)
     {
             SqlConnection sqlConn = new SqlConnection("my connection string");
             .....implementation......
             sqlConn.Close();               
     }   
}

对于选项,在实例化类时打开连接。因此,无论调用者调用RunQuery多少次,连接始终都准备就绪。但是如果应用程序在应用程序的早期实例化DBWrapper,那么在应用程序完成之前,连接将被打开并且什么都不做。此外,它可以在执行期间实例化许多DBWrapper。所以,这有点浪费资源。

对于选项B,它没有选项A具有的问题,但每次调用者调用RunQuery时都必须打开和关闭新连接。我不确定它对性能的影响有多大。

请分享您的专业知识。谢谢你的阅读。

5 个答案:

答案 0 :(得分:6)

出于性能原因,您绝对不想选择B(至少在我遇到的情况下)。 我建议选项C:

class DBWrapper:IDisposable { private SqlConnection sqlConn;

public void EnsureConnectionIsOpen()
{
    if (sqlConn == null)
    {
      sqlConn = new SqlConnection("my connection string");
      sqlConn.Open();
    }

}

public DataTable RunQuery(string Sql)
{
    EnsureConnectionIsOpen();
    implementation......
}

public Dispose()
{
   if(sqlConn != null)
              sqlConn.Close();
}

} 

您可以考虑使用单例模式来确保只有一个DBWrapper实例。

答案 1 :(得分:2)

值得考虑的一些评论:

在管理(可能)长期连接的方法中,在运行查询之前检查连接是否打开很重要。在一段时间之后,NETCF在关闭未使用的连接之前遇到了问题。

在每个查询打开一个新连接的方法中,确保您的连接,命令和(如果使用的话)数据读取器都使用语句或try / finally + dispose()块正确包装以释放连接和锁。

快乐的编码!

答案 2 :(得分:2)

垃圾收集器是在相当复杂的条件下触发的,但基本上它是在内存超过某个限制时调用的,它也会定期调用,但周期不是常量。您永远无法确定何时处理垃圾收集器并因此(在另一次运行中)销毁该对象。有一件事你可以确定垃圾收集器永远不会处理和销毁仍然有引用的对象。例如,通过类上的静态变量引用的对象既不会被处理也不会被销毁。

答案 3 :(得分:1)

选项B更具交易性,具有其优势。 ADO.NET使用隐式连接池,因此您不必担心经常创建SqlConnection的新实例。

您应该考虑使用连接或断开连接的数据模型;因为第二种方法更适合于断开连接的模型。

但正如我上面所说,连接池意味着它在实际上几乎没有区别。

答案 4 :(得分:0)

你可以有一个选项C,在RunQuery中请求打开数据库(如果它没有打开)并关闭处理(打开时)。这样,数据库只在真正需要时打开,并且只打开一次。

所以在伪代码中:

class DBWrapper
{

     public DBWrapper()
     {            
     }

     SqlConnection sqlConn = null; 

     public DataTable RunQuery(string Sql)
     {
             if(sqlConn == null) sqlConn = new SqlConnection("my connection string");
             .....implementation......               
     }   
     public Dispose()
     {
            if(sqlConn != null)
                   sqlConn.Close();
     }

}

还要注意,Dispose被调用的时刻并不总是直接在不再需要该对象之后(例如,在使用该函数之后的函数变量)。据我所知,它将在垃圾收集器收集对象时执行(不是直接)。但我对此并不完全确定。 Web和非Web应用程序之间的此行为也可能不同。