2011-06-02 73 views
1

我正在创建一个将管理与Firebird数据库的连接的类。 Firebird服务将被安装以促进与数据库的多个连接。不幸的是,我的软件部署的环境可能很不稳定,而且我不能始终保证Firebird服务在我尝试连接时运行,或者在建立连接后继续运行。为了集中化错误处理,我做出了决定,我的代码的不同部分不会以任何方式直接与数据库游标一起工作。相反,我会从我的连接管理器中公开query()dml()方法。考虑到下面的代码(为了简洁起见,一些代码不包括在内),这可以起到扩展的作用。Python数据库游标异常时机

class DBConnection(object): 
    # self._conn is an instance of kinterbasdb.connect() 
    def query(self, query, params = None): 
    cursor = self._conn.cursor() 

    if params: 
     cursor.execute(query, params) 
    else: 
     cursor.execute(query) 

    return [[x[0].title() for x in cursor.description]] + [r for r in cursor.fetchall()] 

    def dml(self, query, params = None): 
    cursor = self._conn.cursor() 

    if params: 
     cursor.execute(query, params) 
    else: 
     cursor.execute(query) 

    self._conn.commit() 

当Firebird服务停止或由于某种原因无法访问时,会遇到麻烦。我预计self._conn.cursor()会抛出一个异常,这将使它简单,做这样的事情:

class DBConnection(object): 
    # self._conn is an instance of kinterbasdb.connect() 
    def cursor(self): 
    try: 
     return self._conn.cursor() 
    except: 
     # Error handling code here, possibly reconnect, display alert. 

    def query(self, query, params = None): 
    cursor = self.cursor() 

    def dml(self, query, params = None): 
    cursor = self.cursor() 

不幸的是,没有什么异常,当我请求游标抛出。在拨打电话cursor.execute()之前我不会意识到这个问题。这意味着,如果我想适当集中我的错误处理,我必须做这样的事情:

class DBConnection(object): 
    # self._conn is an instance of kinterbasdb.connect() 
    def cursor(self): 
    try: 
     cursor = self._conn.cursor() 

     cursor.execute("Select NULL From <sometable>") 

     return cursor 
    except: 
     # Error handling code here, possibly reconnect, display alert. 

这需要一个额外的往返到我的数据库,浪费了交易(火鸟数据库有一个硬上限制数据库使用期限内的总交易),并且通常只是感觉错误。我想知道,有没有人遇到类似Python数据库API的其他实现,如果有的话,他们是如何克服的?

回答

1

我正在测试对我的课程进行以下修改,我相信这些修改将以最少的代码重复实现我想要的集中式处理。它们还简化了查询和dml方法,并且消除了我想避免的额外查询(心跳)。

class DBConnection(object): 
    # self._conn is an instance of kinterbasdb.connect() 
    def query(self, query, params = None): 
    cursor = self._conn.cursor() 

    self.execute(cursor, query, params) 

    return [[x[0].title() for x in cursor.description]] + 
      [r for r in cursor.fetchall()] 

    def dml(self, query, params = None): 
    cursor = self._conn.cursor() 

    self.execute(cursor, query, params) 

    self._conn.commit() 

    def execute(self, cursor, query, params = None): 
    try: 
     if params: 
     cursor.execute(query, params) 
     else: 
     cursor.execute(query) 
    except Exception, e: 
     # Handling 
0

与Firebird的数据库连接遭遇连接检测问题作为标准TCP/IP连接。也就是说,连接在使用之前不容易被检测为“死亡”。在TCP/IP世界中解决这个问题的方法是使用KeepAlive(仍然约15分钟的检测周期)和明确的心跳。您发送查询以进行检测与发出检测信号以查看它是否仍然存在相似。

当您在游标上执行SQL语句时,您将在断开连接时发生异常。检测连接失败的适当位置正在使用。集中式错误检查是一个很好的目标,但是如上所述,您仍然保留在返回有效的游标对象和稍后执行之间与Firebird的连接丢失的可能性(即,您仍然可能在dml的execute()调用中失败)功能)。