程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> MYSQL客戶機程序3—產生連接代碼模塊

MYSQL客戶機程序3—產生連接代碼模塊

編輯:關於MYSQL數據庫
 6.4 客戶機程序3—產生連接代碼模塊

  對於我們的第三個客戶機程序,即客戶機程序3,通過將它封裝到函數do_connect() 和do_disconnect() 中,將使連接和斷開代碼更加模塊化,這樣可以很容易地由多個客戶機程序使用。這提供一種選擇,可將連接代碼精確地嵌入到main() 函數中。無論如何,對在應用程序過程中套用老調的任何代碼都是一個好主意。將它放在可以通過多個程序訪問的函數中,而不是在每個程序中都編寫一遍。如果修正這個函數中的一個錯誤或對這個函數作了一些改進,則可只更改一次,只要重新編譯就可以使用這個函數的所有程序都被修正或利用這種改進。同樣,編寫一些客戶機程序,以便在它們執行過程中可以若干次地連接和斷開。如果將安裝和卸載方法放在連接和斷開的函數中,則編寫這樣一個客戶機更加容易。封裝策略如下所示:

  1) 將公用代碼分離到一個獨立的源文件( common.c)的包裝函數中。

  2) 提供一個頭文件,common.h,其中包括該公共例程的原型。

  3) 在使用公共例程的客戶機源文件中包括common.h。

  4) 將公共源文件編譯成目標文件。

  5) 將公共目標文件連接到您的客戶機程序中。

  用這些策略,讓我們構造do_connect() 和do _ disconnect( )。

  do_connect() 代替對mysql_init() 和mysql_real_connect() 的調用,並替換錯誤打印的代碼。除了不傳遞任何連接處理程序外,您可以像mysql_real_connect() 一樣調用它。do_connect() 分配並初始化這個處理程序,然後,在連接後返回一個指向它的指針。如果do_ connect() 失敗,則在打印一個錯誤消息以後,返回NULL(那就是說,調用do_connect() 並獲取返回值NULL的任何程序都可以簡單地退出,而不用擔心打印消息的本身)。do_ disconnect () 產生一個指向連接處理程序的指針,並調用MySQL_close ()。這裡是common.c 的代碼:

  

  common.h 聲明common.c 中這些例程的原型:

  

  要想訪問公共例程,應在源文件中包括common.h。請注意, common.c 同樣包括common.h。那就是說,如果common.c 中的函數定義與頭文件中的聲明不匹配,則立即得到一個編譯程序警告。同樣,如果更改common.c 中的調用次序而沒有相應地更改common.h,則當重新編譯common.c 時,編譯程序將發出警告。

  有人會問為什麼要發明包裝函數do _ disconnect( ),而它使用得還這麼少。do _ disconnect( )和mysql_close() 等價。但是假設在斷開連接時,都有一些要執行的額外清除。則通過調用已經完全控制的包裝函數,可以修改該包裝函數來做需要的事情,對於所做的任何斷開的操作,這種更改統一生效。如果直接調用MySQL_ close( ),則不能做到這點。在前面,筆者聲稱對在多個程序中或在單個程序內部多處使用的函數中,將代碼封裝成模塊化代碼是有好處的。前面介紹一個理由,還有一些理由參見下面的兩個樣例。

  ■ 樣例1在MySQL3 .22以前的版本中,MySQL_real_connect() 調用與它現在稍微有些不同:即沒有數據庫名稱參數。如果想利用舊的MySQL客戶機庫使用do _ connect( ),則它不能工作。然而,可以修改do _ connect( ),使它可在3.22版以前的版本上運行。這就

  意味著,通過修改do _ connect( ),可以增加使用它的所有程序的可移植性。如果將這些連接代碼直接嵌入到每個客戶機中,則必須獨立地修改它們中的每一個。

  要想修正do _ connect( ),使它可以處理mysql_real_connect() 的舊格式,那麼就可以使用包括當前MySQL版本MySQL_VERSION_ID 宏。更改了的do_connect() 測試MySQL_VERSION_ID 值,並使用MySQL_real_connect() 的正確格式:

  

  

  

  除了下述兩點以外, do_connect() 的這個修改過的版本和前一個版本在外觀上是完全一樣的:

  ■ 它不將db_name 參數傳遞給MySQL_real_connect() 較早的格式,因為那個版本沒有這樣的參數。

  ■ 如果數據庫名稱是非NULL 的,則do_connect() 調用MySQL_select_db() 使指定的數據庫為當前數據庫(這類似於沒有db_name 參數的效果)。如果沒有選擇這個數據庫,則do_connect() 打印一個錯誤消息,關閉連接,並返回NULL 來表示失敗。

  ■ 樣例2 該樣例是在對第一個樣例的do_connect() 做更改的基礎上建立的。那些更改導致對錯誤函數mysql_errno() 和MySQL_error() 的三組調用。每次都將報告問題的這些代碼書寫出來是非常討厭的。除此之外,錯誤所打印出的代碼看起來不舒服,讀起

  來也困難。而讀下面這樣的代碼就比較容易:

  print_error (conn, “mysql_real_connect() failed”) ;所以,讓我們在print_error() 函數中封裝錯誤打印。即使conn 為NULL,也可以編寫它來做一些明智的事情。也就是說,如果MySQL_init() 調用失敗,可以使用print _error( )。而且沒有混合調用(一些為fprintf ( ),一些為print _ error( ))。我聽到一些反對意見:“為了想報告一個錯誤而又不必每次都調用兩個錯誤函數,所以使代碼故意編寫得難以閱讀,以說明封裝樣例更好。其實不用真的寫出所有的錯誤打印代碼:只將它編寫一次,然後當再次需要時就使用拷貝和粘貼即可。”這種觀點是正確的,但我持反對意見,理由如下:

  ■ 即使使用拷貝和粘貼,用較短的代碼段進行起來也更容易。

  ■ 每當報告錯誤時,無論是否願意每次調用兩種函數,將所有的錯誤報告代碼書寫得很長,會產生不一致性。將錯誤報告的代碼放在容易調用的包裝函數中,就可以減少這種想法並提高編碼的一致性。

  ■ 如果決定修改錯誤消息的格式,則只需要在一個地方而不是整個程序中做更改,這樣就要容易許多。或者,如果決定將錯誤消息編寫到日志文件中而不是(或除此以外還)編寫到stderr 中,則只須更改print _ error ( ),這就更容易。這種方法可能犯更少的錯誤,而且再一次減少了工作量和不一致的可能性。

  ■ 當測試程序時,如果使用調試程序,將斷點放在錯誤報告的函數中,則當它偵測出一個錯誤條件時,調試程序是使程序中斷的一種便利方法。以下是錯誤報告函數print _ error( )的使用舉例:

  

  

  主源文件client3.c 與clIEnt2.c 一樣,但是所有嵌入的連接和斷開代碼都利用調用包裝函數來刪除和替換了。如下所示:

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved