首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IDbConnection异常

IDbConnection异常
EN

Stack Overflow用户
提问于 2009-07-17 17:18:43
回答 2查看 3K关注 0票数 1

我有一个用于Sql或Oracle连接的IDbConnection。我可以打开它,然后通过连接读取数据或保存数据。但是,当工作完成后,我尝试关闭连接。然后我得到了一个异常:“内部.Net框架数据提供程序错误1”。

以下是关闭连接的一些代码:

代码语言:javascript
复制
if (conn != null) // conn is IDbConnectin
{
  if (conn.State == System.Data.ConnectionState.Open)
  {
    conn.Close(); // bung! exception
  }
  conn.Dispose();
}
conn = null;

在安全关闭连接之前,我还需要检查什么吗?

EN

回答 2

Stack Overflow用户

发布于 2009-07-17 18:02:40

我知道这听起来可能不能直接解决您的问题,但是IDbConnection是IDisposable,所以请将使用它的代码包装在using {}块中。

为什么?

您可能知道,在using {}块的末尾会调用Dispose()。而且,在每个IDbConnection实例中,调用Dispose()都会间接调用Close()。但是使用using还有一个额外的好处,它可以防止您完全遇到这个问题--通过使用using,您必须在相同的上下文中创建、打开、关闭和处理连接。

我发现人们遇到的大多数问题都是当他们使用终结器或单独的线程来处理他们的连接对象时。对我来说,还有一种更大的味道,他们让他们的一次性对象保持存活的时间太长了一点,可能是在同一个类的多个成员之间共享连接。

换句话说,当您传递connection对象时,您可能会想要编写如下内容:

代码语言:javascript
复制
class AccountService {
   private IDbConnection conn;
   internal AccountService(IDbConnection connection) {
     this.conn = connection;
   }

   public Account GetAccount(String id) {
     IDbCommand command = conn.CreateCommand();
     conn.Open;
     Account a = Account.FromReader(command.Execute(Strings.AccountSelect(id)));
     conn.Close;  // I remembered to call Close here
     return a;
   }

   // ... other methods where I Open() and Close() conn

   // hopefully not necessary since I've been careful to call .Close(), but just in case I forgot or an exception occured
   ~AccountService() { 
     if (conn != null) 
     {
       if (conn.State == System.Data.ConnectionState.Open)
       {
         conn.Close(); 
       }
       conn.Dispose();
     }
     conn = null;
   }
}

如果你使用了using,你甚至不需要考虑使用终结器:

代码语言:javascript
复制
// IDbFactory is custom, and used to retrieve a Connection for a given Database
interface IDbFactory {
    IDbConnection Connection { get; }
}

class AccountService {
  private IDbFactory dbFactory; 
  internal AccountService(IDbFactory factory) { 
    this.dbFactory = factory;
  }

  public Account GetAccount(String id) {
    using (IDbConnection connection = dbFactory.Connection) { 
      using (command = connection.GetCommand()) {
        connection.Open();
        return Account.FromReader(command.Execute(Strings.AccountSelect(id)));
      } 
    } // via using, Close and Dispose are automatically called
  }

  // I don't need a finalizer, because there's nothing to close / clean up

}

using规则也有例外,特别是如果一次性对象的构造成本很高,但如果您不使用using,那么每100次中就有99次是有异味的。

票数 2
EN

Stack Overflow用户

发布于 2009-07-17 17:28:22

我认为你在其他线程或Finilize方法中调用了close方法。不要在类的Finalize方法中对Connection、DataReader或任何其他托管对象调用Close或Dispose。在终结器中,应该只释放类直接拥有的非托管资源。如果您的类不拥有任何非托管资源,则不要在类定义中包含Finalize方法。请参阅here

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1144622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档