Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#数据库包装器设计_C#_Database_Wrapper_Design Patterns - Fatal编程技术网

C#数据库包装器设计

C#数据库包装器设计,c#,database,wrapper,design-patterns,C#,Database,Wrapper,Design Patterns,我正在为C#设计一个数据库包装器。 以下是我的两个选择: 备选方案A: class DBWrapper:IDisposable { private SqlConnection sqlConn; public DBWrapper() { sqlConn = new SqlConnection("my connection string"); sqlConn.Open(); } public Dat

我正在为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时,都必须打开和关闭新连接。我不确定这会对演出造成多大的影响


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

一些值得考虑的评论:

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

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


快乐编码

出于性能原因,您肯定不想使用选项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();
}

} 

您可能会考虑使用单模式来确保您的DbWrPrAPER只有一个实例。

选项B更具有事务性,这有它的优点。NET使用隐式连接池,因此您不必担心频繁创建SqlConnection的新实例

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


但正如我上面所说的,连接池意味着它实际上没有任何实际意义。

您可以使用选项C,其中数据库在RunQuery中根据请求打开(如果未打开),在disposed时关闭(打开时)。这样,数据库只在真正需要时打开,并且只打开一次

所以在伪代码中:

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应用程序之间也可能有所不同。

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

它们往往会在这里得到一个坏名字,但对单例设计模式有了解,这是我唯一一次使用singletons@acqu13sce:为什么这个坏名字?这是模仿能力的原因吗?我只是顺便看了一些评论,包括这个社区维基,我个人认为它们有自己的位置,但可能会被过度使用。你写完包装了吗?在网上的任何地方都能看到代码吗?它是开源的吗?它还包括对象映射器吗?请注意,在使用singleton模式时,您可能会遇到一些关于多线程的问题(如果实现的模式不正确)。虽然单线程通常是这类代码的良好解决方案,但在应用程序中使用静态时,人们应该始终保持警惕并检查多线程问题。单线程只是线程之间共享对象的一种方法,但显然,一旦在线程之间共享对象,您就必须仔细设计多线程,无论它们是如何共享的。如果您在线程之间共享数据库连接(在web场景中,用户之间也共享数据库连接),您可能会遇到“有趣”的情况。它还将禁止您拥有多个连接。在父->子关系中收集数据时,有时需要有多个连接,在这种情况下,您通常会打开第二个连接以获取子连接,而第一个连接用于收集父连接。让我问一个转储问题:对于web应用程序,当两个人同时请求一个页面不考虑多个线程对吗?当然是,请参阅更多细节。谢谢您的提醒。对于选项A,如果我确保我的类没有公开任何函数来关闭连接,并且总是有一个构造函数来打开连接,那么它应该是可以的,对吗?是的,我正在使用“using”语句。@dreteh:我建议在使用之前提供一个私有/受保护的属性来检查连接。类似于
受保护的SqlConnection连接{get{if(sqlConn.State==ConnectionState.Closed)sqlConn.Open();return sqlConn;}}
。作为免责声明,我从未遇到过框架关闭compact框架之外连接的问题。对于一个完整的框架应用程序来说,这个建议可能有些过头了。我很想知道,在进入待机或休眠状态的笔记本电脑上,连接是否会自动关闭。但我可以看到,这种设计也会有选项a的问题,因为想象一下,如果RunQuery在执行的一开始就被调用,并且在执行结束之前不再使用。这是真的,但是当首先需要在示例A打开时构造对象。如果你想收紧你的寿命