DBX中的 SQLTable / SQLQuery / SQLDataSet 都有支援「RecordCount」函式(統計資料集合現有多少筆數)
實際在用的時候發現並不是這麼好用,常常 run 到該處就發生例外錯誤(Exception)
不少人認為這是DBX的BUG...
最近閒來沒事在查這方面的資訊,發現原來BCB的HELP中有解釋不能應用的場合
原來DBX的元件是由「TCustomSQLDataSet」繼承「TDataSet」而來
然「TCustomSQLDataSet」有改寫 RecordCount 的些許內容,一般簡易查詢依然可以利用
但如果遇到以下情況則會跳出例外錯誤:
1. The dataset represents stored procedure.
1. 資料集為 Stored Procedure 表示式
2. The dataset represents a query that contains parameters.
2. 資料集為帶有參數查詢的表示式
3. The dataset represents a multi-table join.
3. 資料集為多表合併的表示式
不過HELP中並沒有提到這樣的限制的理由 (汗)
解決的方式有以下兩種:
1. 利用ClientDataSet來處理RecordCount
2.使用SQL的COUNT(*)來統計
以上,做個小參考吧~~~(笑)
2009/04/28
DBeXpress的一些觀念
話說DBeXpress是B社強力主推的軟技術之一
但鮮少有資料可供參考
討論它的專書繁中+簡中的…大約4本吧
而有提到的書籍,無一不說DBX的效能好,但…
說效能不錯,那是有條件的!
就先拿BDE來說好了,B社資料連結技術的開山元祖
速度快不快,說真的,在單機架構中,應該是沒有任何的引擎比它快
(就連最新的DBX4也才只比BDE快0.X秒)
缺點:
封裝麻煩
說真的,BDE除了這點外,大概沒其它問題(…是我沒用到過)
而DBX呢?
速度嘛…M$SQL輸ADO(大),單機輸BDE(超大),C/S則還需看BDE的SQL LINK及ODBC效能才有機會勝出…
DBX的效能…或許在5~6版之後能真正超越BDE吧
那,DBX的優勢在哪邊?
1.封裝簡單
只需要把 MIDAS 及 DBX+DB Client所需的DLL包在一起,直接封裝即可,快速簡單
2.架構明確
以往習慣BDE的B社愛好者(被逼?),一但必須把原1~2-TIER的架構晉升為N-TIER時,往往會因架構落差太大導致轉換不易
而DBX採行的則是「準n-tier」架構,讀取資料時採單向取出,寫入資料時則交由DATASNAP方式寫入
各司其職,取「單向取出」及「MIDAS寫入」二者優點,得到最大效能
(慢就是慢在MIDAS,所以效能慢也不能全怪DBX)
提了這麼多,那DBX的架構是什麼東西?
DBX元件 + DataSetProvider + ClientDataSet
這就是完整的DBX架構
某書曾寫DBX + StringGrid的方式簡直是大誤......
N-TIER所用到的元件則是…
(BDE / ADO / DBX) + DataSetProvider |<-Server 切 Client->| (DCOM / Socket) + ClientDataset
如何?有沒有像一點?如此切開就成了n-tier架構
接下來要討論的課題是
這樣的DBX要怎麼在專案中設計?
以下的內容不一定是正規寫法,也歡迎提出討論
1.視時機使用SQLTable/SQLQuery及ClientDataSet操作資料存取元件
這種方式看起來沒啥不好,在c/s設計上也沒有問題,但在未來移轉到n-tier時,需要變更的地方可不少
(也就是說,仍採用與BDE相同的設計模式)
2.將ClientDataSet直接取代成TTable / TQuery來使用
把SQLTable及DataSetProvider藏在DataModule內,完全使用ClientDataSet操作
這樣的方式更能貼近N-TIER的程式寫法,若未來有升級的空間,可考慮這樣的寫法
但在1~2-TIER上設計時往往會有脫褲子放屁的感覺
再者,由於大部份的情況都在DataSetProvider做in/out動作,效率上會顯得更為慢些
(在單機的情況來說,這並不明顯)
在設計性與未來延伸性來說,會是設計師的一門課題
不過也因為這個原因,讓資料庫程式設計變得富有趣味性及變化性。
但鮮少有資料可供參考
討論它的專書繁中+簡中的…大約4本吧
而有提到的書籍,無一不說DBX的效能好,但…
說效能不錯,那是有條件的!
就先拿BDE來說好了,B社資料連結技術的開山元祖
速度快不快,說真的,在單機架構中,應該是沒有任何的引擎比它快
(就連最新的DBX4也才只比BDE快0.X秒)
缺點:
封裝麻煩
說真的,BDE除了這點外,大概沒其它問題(…是我沒用到過)
而DBX呢?
速度嘛…M$SQL輸ADO(大),單機輸BDE(超大),C/S則還需看BDE的SQL LINK及ODBC效能才有機會勝出…
DBX的效能…或許在5~6版之後能真正超越BDE吧
那,DBX的優勢在哪邊?
1.封裝簡單
只需要把 MIDAS 及 DBX+DB Client所需的DLL包在一起,直接封裝即可,快速簡單
2.架構明確
以往習慣BDE的B社愛好者(被逼?),一但必須把原1~2-TIER的架構晉升為N-TIER時,往往會因架構落差太大導致轉換不易
而DBX採行的則是「準n-tier」架構,讀取資料時採單向取出,寫入資料時則交由DATASNAP方式寫入
各司其職,取「單向取出」及「MIDAS寫入」二者優點,得到最大效能
(慢就是慢在MIDAS,所以效能慢也不能全怪DBX)
提了這麼多,那DBX的架構是什麼東西?
DBX元件 + DataSetProvider + ClientDataSet
這就是完整的DBX架構
某書曾寫DBX + StringGrid的方式簡直是大誤......
N-TIER所用到的元件則是…
(BDE / ADO / DBX) + DataSetProvider |<-Server 切 Client->| (DCOM / Socket) + ClientDataset
如何?有沒有像一點?如此切開就成了n-tier架構
接下來要討論的課題是
這樣的DBX要怎麼在專案中設計?
以下的內容不一定是正規寫法,也歡迎提出討論
1.視時機使用SQLTable/SQLQuery及ClientDataSet操作資料存取元件
這種方式看起來沒啥不好,在c/s設計上也沒有問題,但在未來移轉到n-tier時,需要變更的地方可不少
(也就是說,仍採用與BDE相同的設計模式)
2.將ClientDataSet直接取代成TTable / TQuery來使用
把SQLTable及DataSetProvider藏在DataModule內,完全使用ClientDataSet操作
這樣的方式更能貼近N-TIER的程式寫法,若未來有升級的空間,可考慮這樣的寫法
但在1~2-TIER上設計時往往會有脫褲子放屁的感覺
再者,由於大部份的情況都在DataSetProvider做in/out動作,效率上會顯得更為慢些
(在單機的情況來說,這並不明顯)
在設計性與未來延伸性來說,會是設計師的一門課題
不過也因為這個原因,讓資料庫程式設計變得富有趣味性及變化性。
2009/04/11
在史瓦濟蘭九天的回憶錄(一)
話說去史瓦濟蘭,到底是好,還是不好?


說真的,沒一天好,沒有一天是好的!
(這就是愛台灣啦!哈哈!)
因為敝公司的業務平日都有在做面子,所以在那邊真的很能感受客戶對我們的善意
也看到了當地的好人,當然,壞人也不少啦,但與南非比起來,史國民情算是相當優良的了
出發第一天從台灣出發,飛到香港後,等了3小時才搭上預計的班機,當時是晚上,而南非當地則是白天。坐上飛機,發現座位旁沒人,心想真幸運,但沒想到之後坐在我旁邊的居然是位高胖的黑人(多胖?185cm / 120公斤有吧),就是坐著還會卡到我,真是大隻……
抵達南非時的機上照片
飛機飛得很快,平均是900km / hr,我覺得就像上演現代版夸父追日一般,當然,太陽沒被我們追到,連月亮都跑得比我們還要快,到最後,我們又被太陽給追上了,呵!
「這邊是德本機場!」不遠處的香港旅行團團員盼盼在討論這件事情
呃!?這跟我們預計的不太一樣,我們不是應該到約翰尼斯堡嗎?
之後的廣播告知:因南非天候不佳,必須先到德本機場等候,等天氣好一點,再飛到目的地。
之後我就開始觀查旁邊的大隻佬,呼吸聲真大…下飛機時還會把垃圾丟到我位置前的置物袋……是我太大驚小怪嗎?但…好像是當地的民族性…或許吧
2009/04/08
[轉貼]心得分享 : 參數檔 (INI 檔) 處理
來源:心得分享 : 參數檔 (INI 檔) 處理
INI 檔應用的歷史從 Windows 3.1就已存在,雖然它也是文字檔的一種,但它利用「節區(Section)」及「識別字(KeyWord)」觀念,類似資料庫的索引,所以用來當作少量 變數資料的儲存器非常適合,除變數管理容易外尚可做程式流程控制,市售套裝軟體有用 ini 檔來控制其軟體版本例子,其主執行檔可能只有一個,但依 INI 檔設定可開放其全功能版(豪華版)與非全功能版;INI檔案 Size 雖然有 64k的限制,但已足夠存放上百個變數資料;在 32 位元系統上,正統取代 INI 機能的方法為使用 Windows Regist,但為了儲存Windows 作業系統本身的資訊,Regist已夠龐大,如果我們每個應用程式又去 Regist內挖一塊空間當作自己儲藏變數或參數的地方,會讓 Regist變得更龐大更複雜,所以筆者還是建議每個程式都使用自己的INI檔來儲存自己的變數,況且 INI檔不會被淘汰,連 Linux Kylix 下都看得到其蹤影
■ 應用實例
假設程式中需要紀錄目前發票號碼(invo_no)、交易序號(tran_no),而每次交易完都要將這兩個變數值加1,若程式從頭到尾都不關機,那沒有 問題,程式會記錄目前的發票號碼及交易序號已排到幾號;但若程式中途有關機後,下次開機,程式怎知發票號碼及交易序號已排到幾號?所以除了將變數資料存於 資料庫中外,更簡單的方法就是使用INI檔來記錄變數值,在程式重新啟動時再將變數值取回,所以該INI檔內容可能長得如下:
[Varible]
invo_no=00000005
tran_no=3
其中,用中括號刮起來的Variable就是「節區(Section)」名稱(可自訂),而其內的 INVO_NO、TRAN_NO則稱為「識別字(KeyWord)」(可自訂);不可有相同名稱的兩個節區(Section),但不同的節區中可有相同名 稱的識別字(KeyWord),取用時按節區(Section)索引分開取用,如下圖:
[Varible]
invo_no=00000005
tran_no=3
[Varible_2]
invo_no=00000007
tran_no=5
■ 程式實例
接下來我們介紹使用 INI 檔來儲存或取回變數的方法,在程式中要使用 INI 檔有幾個步驟:
1.程式開頭必須 #include "inifiles.hpp"
2.程式中首先需建立一個 INI 物件以對應實際的 INI 檔,不用時再釋放這個 INI 物件,通常 INI 檔實 體與主執行檔存在同一路徑,甚至檔名也和主執行檔相同,但副檔名則為 *.ini
3.使用 INI 物件的某些方法(Method)來存取變數,取用的方法依變數型態有下列幾種方法(假設這個 INI 物件名為 MyIni)
MyIni->ReadInteger(節區名,識別字,整數Default值);
MyIni->ReadString(節區名,識別字,字串Default值);
MyIni->ReadBool(節區名,識別字,布林Default值)
4.寫入的方法依變數型態也有下列幾種方法
MyIni->WriteInteger(節區名,識別字,欲寫入之整數變數值);
MyIni->WriteString(節區名,識別字,欲寫入之字串變數值);
MyIni->WriteBool(節區名,識別字,欲寫入之布林變數值)
以下為一完整使用INI程式碼的範例
■ INI 物件的生命週期
在上面的程式碼中,可以看見我們把 INI 物件的建立寫在 FormCreate 事件中,而釋放 INI 物件則寫在 FormClose 事件中;事實上,變數真正寫到實體檔案中,是在INI 物件釋放的時候(也就是類似關閉檔案動作);平常則只是暫存於記憶體中,如此可減少磁碟 I/O 動作,但若程式不正常關閉,則INI 物件來不及將暫存於記憶體中的變數存檔,會導致欲存檔的變數遺失;所以為保險起見,我們可在準備寫入變數的時候才去建立 INI 物件,存入後馬上釋放 INI 物件以確保寫入實體檔案中,但這樣卻會增加磁碟I/O讀寫頻繁,其中的斟酌端看應用方向的特性。
INI 檔應用的歷史從 Windows 3.1就已存在,雖然它也是文字檔的一種,但它利用「節區(Section)」及「識別字(KeyWord)」觀念,類似資料庫的索引,所以用來當作少量 變數資料的儲存器非常適合,除變數管理容易外尚可做程式流程控制,市售套裝軟體有用 ini 檔來控制其軟體版本例子,其主執行檔可能只有一個,但依 INI 檔設定可開放其全功能版(豪華版)與非全功能版;INI檔案 Size 雖然有 64k的限制,但已足夠存放上百個變數資料;在 32 位元系統上,正統取代 INI 機能的方法為使用 Windows Regist,但為了儲存Windows 作業系統本身的資訊,Regist已夠龐大,如果我們每個應用程式又去 Regist內挖一塊空間當作自己儲藏變數或參數的地方,會讓 Regist變得更龐大更複雜,所以筆者還是建議每個程式都使用自己的INI檔來儲存自己的變數,況且 INI檔不會被淘汰,連 Linux Kylix 下都看得到其蹤影
■ 應用實例
假設程式中需要紀錄目前發票號碼(invo_no)、交易序號(tran_no),而每次交易完都要將這兩個變數值加1,若程式從頭到尾都不關機,那沒有 問題,程式會記錄目前的發票號碼及交易序號已排到幾號;但若程式中途有關機後,下次開機,程式怎知發票號碼及交易序號已排到幾號?所以除了將變數資料存於 資料庫中外,更簡單的方法就是使用INI檔來記錄變數值,在程式重新啟動時再將變數值取回,所以該INI檔內容可能長得如下:
[Varible]
invo_no=00000005
tran_no=3
其中,用中括號刮起來的Variable就是「節區(Section)」名稱(可自訂),而其內的 INVO_NO、TRAN_NO則稱為「識別字(KeyWord)」(可自訂);不可有相同名稱的兩個節區(Section),但不同的節區中可有相同名 稱的識別字(KeyWord),取用時按節區(Section)索引分開取用,如下圖:
[Varible]
invo_no=00000005
tran_no=3
[Varible_2]
invo_no=00000007
tran_no=5
■ 程式實例
接下來我們介紹使用 INI 檔來儲存或取回變數的方法,在程式中要使用 INI 檔有幾個步驟:
1.程式開頭必須 #include "inifiles.hpp"
2.程式中首先需建立一個 INI 物件以對應實際的 INI 檔,不用時再釋放這個 INI 物件,通常 INI 檔實 體與主執行檔存在同一路徑,甚至檔名也和主執行檔相同,但副檔名則為 *.ini
3.使用 INI 物件的某些方法(Method)來存取變數,取用的方法依變數型態有下列幾種方法(假設這個 INI 物件名為 MyIni)
MyIni->ReadInteger(節區名,識別字,整數Default值);
MyIni->ReadString(節區名,識別字,字串Default值);
MyIni->ReadBool(節區名,識別字,布林Default值)
4.寫入的方法依變數型態也有下列幾種方法
MyIni->WriteInteger(節區名,識別字,欲寫入之整數變數值);
MyIni->WriteString(節區名,識別字,欲寫入之字串變數值);
MyIni->WriteBool(節區名,識別字,欲寫入之布林變數值)
以下為一完整使用INI程式碼的範例
//------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" #include "inifiles.hpp" //要 include 這個東西才有 TIniFile 類別 //------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; TIniFile *MyIni; //------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { //建立 ini 物件及實體存放路徑 MyIni = new TIniFile(ChangeFileExt( Application->ExeName, ".ini" ) ); //讀取變數(若變數值不存在則用自動使用 Default 值) Left=MyIni->ReadInteger( "Form","Left",100); Caption=MyIni->ReadString( "Form","Caption","Default Caption"); } //------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { //將變數寫入 ini 物件 MyIni->WriteInteger("Form","Left",Left); MyIni->WriteString("Form","Caption",Caption); // 釋放 ini 物件 delete MyIni; } //-------------------------------------------------------
■ INI 物件的生命週期
在上面的程式碼中,可以看見我們把 INI 物件的建立寫在 FormCreate 事件中,而釋放 INI 物件則寫在 FormClose 事件中;事實上,變數真正寫到實體檔案中,是在INI 物件釋放的時候(也就是類似關閉檔案動作);平常則只是暫存於記憶體中,如此可減少磁碟 I/O 動作,但若程式不正常關閉,則INI 物件來不及將暫存於記憶體中的變數存檔,會導致欲存檔的變數遺失;所以為保險起見,我們可在準備寫入變數的時候才去建立 INI 物件,存入後馬上釋放 INI 物件以確保寫入實體檔案中,但這樣卻會增加磁碟I/O讀寫頻繁,其中的斟酌端看應用方向的特性。
//------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { TIniFile *MyIni; MyIni = new TIniFile(ChangeFileExt( Application->ExeName, ".ini" ) ); MyIni->WriteInteger("Form","Left",Left); MyIni->WriteString("Form","Caption",Caption); delete MyIni; } //-------------------------------------------------------
2009/03/13
史瓦濟蘭前外一章
星期六原本要去史瓦濟蘭
在第二次的複診中,醫生提到我的血液檢查結果是沒有A、B型肝炎抗體,也沒有抗原(也就是還沒得病的意思),建議我打A、B型肝炎的二合一疫苗
雖然不清楚費用要多少,但以自費的慣例來看,沒有破NT2000應該是不可能
而且,這也不在這次去史瓦濟蘭的事前重要準備項目之一,所以就向醫生表示沒有施打的意願
在這之後…醫生一直強調這個疫苗只有台大有,一般坊間是沒有二合一的(REPEAT*n)
還直說沒打會後悔等類的話
(事後去找了才發現,連署立醫院都沒聽過有這二合一的疫苗,可見這藥是很新的(一定更貴)
而且這次我還遇上了全台A肝疫苗大缺貨,有錢也買不到的疫苗…至此,我還真有點後悔…)
在會診結束之後,醫生就說我如果要去一般醫院,建議我去印診斷報告
到底要印什麼咧?是只要印血液檢查報告呢?還是連醫生的手寫稿也要呢?
這個問題除了我要去的醫院(診所)知道外,我看全台大也沒人知道
為了避免還要再來一趙,所以也就一併把醫生的手寫病例給申請了出來
不申請還好,一申請……
老闆生氣了...........................................
除了被叫去老闆室落鑽外,去到當地還被冷嘲熱諷……
一整個小心眼的老闆啊……
除了被叫去老闆室落鑽外,去到當地還被冷嘲熱諷……
一整個小心眼的老闆啊……
2009/03/07
行前的健康檢查
最近為了到史瓦濟蘭出差,還得千里迢迢地跑到台大去做健檢
在經過無止境的排隊、等待…只得到3分鐘的問診時間…
我說啊…這c/p值也太低了吧!
從鄉下來的我,除了只會騎車外,很少坐其它的交通工具
坐捷運時,拿著感應幣在入口刷半天進不去 @@
在那邊卡了30分鐘,只看到其它人拿著藍綠相間的卡刷一下就進去了,為什麼我還在入口處不得其門而入呢?
站務人員終於看不下去了,走過來大聲地向我說
「先生!卡片要放到螢幕下面的那個感應器才會有效果!」
呃…原來科技還沒這麼先進哦!
就這樣,沒坐過幾次捷運的我,終於在此時此刻用力地把這個「關鍵」地步驟記了起來…
(突然很想去野外趕羚羊…)
雖說坐捷運就很頭痛了,但還不如坐火車,月台、時刻、對號、車別…
光是買票坐火車就讓我一個頭兩個大,尤其是這諾大的台北車站
先投錢再按按鈕?還是先按鈕再投錢幣?
身為台北俗的一員,這30分鐘我依然沒放過…
好不容易,終於出票了,拿起票券,上面寫著:
19元。
我記得我是投20元吧,怎麼還有壹元沒掉下來?難道是退到別的地方?
出票 / 退幣口
沒錯!依然是這個地方!
於是我又在售票機這邊挖挖挖、等等等
我的壹圓~~~~~~~!!!
這是上天懲罰我搭訕美女醫生的罪孽嗎!我下次不敢了! ><
於是,我懷著贖罪的心情,離開了這萬惡地售票機
好在,台鐵的入口只有臭臉剪票員,沒有趕羚羊感應器
「那個,請問這張票要去哪個月台?」我說
「嗯嗯…這個就是第3月台。」
「那下班車什麼時候會到呢?班次在哪邊可以看到?」
「……」
剪票員不耐地指著上面的電子看板說:
「上面這個……(你自己不會看哦)……就是這班自強號啦!時間哦,還剩一分鐘車就要開了,趕快去!」
於是,我又被趕羚羊了,今天我跟野生動物還真是有緣
上了月台,怎麼兩邊都有火車!我是要坐哪一台!怎麼會沒有往北往南的指標!
時間不容我再考慮了,於是我就直覺的選了一台坐上去
「Excuse me!」
一位金髮正妹跑了過來
「This......」她拿著手上的票券給我看,並且指著我坐上的火車
票券上寫著:台北 - 嘉義
雖然我不是要去嘉義,只知道如果這班車是往南,就一定會到嘉義
於是我便不假思所地說:
「YA!!!」
隨後便進車廂內找位子了,過了不久,看到那位金髮正妹也上了車
「糟,我自己也不知道這班車是往北還是往南,如果是往北怎麼辦…」
內心的徬徨與不安擁上心頭,一直到火車啟動…
過了許久後,終於到了下一站,熟悉地廣播聲響起…
「本站是板橋站,請……」
沒錯!這班車是往南!我猜對了!
終於可以放下心中的不安,在這短短地旅程中,可以放心地小瞇一下了!
放下心中的不安,身心獲得了舒展,睡吧,可憐的孩子
火車再度出發,就快結束旅程了
能夠幫助別人,真是一件快樂地事情,真是令人開心
………………
廣播再度響起,我也準備要下車了。
「各位旅客,現在即將抵達的是本列車的終點站:樹林站,本列車將於………」
!
我有沒有聽錯!這站是終點站!!!
國語、台語、客語、英語…重複聽了八遍,我確定台鐵沒說錯…而我,也沒聽錯…
「真是丟臉丟到家了!」我心裡吶喊著
滿懷著不安,歉咎的心情,開了門之後,我似沒了命地逃出了車站
「對不起!我下次再也不亂說話了啊啊啊!」
不知道那個老外後來有沒有順利去到嘉義了。
(本篇完)
2009/03/05
要去史瓦濟蘭了!
我不想去!
一句話,一個跟案子只扯上10%的小工程師,就這樣準備到史瓦濟蘭去了。
我也不想去啊…
但,又能怎辦呢?老闆不是我,家裡還有 7 小要照顧…
「喀噠!」(骨拆聲)
所以只好為2斗米腰斬了!(泣)
究竟史瓦濟蘭是什麼樣的地方呢?
一、台灣的邦交國
二、愛滋病大國(全球平均最短命的國家之一)
三、季節性虐疾產出!(傳說蚊子跟手掌一樣大)
四、一定要煮沸才能喝的水(水裡都有血吸蟲)
……這是什麼國家啊……
一整個亂七八糟……
雖說只要潔身自愛點,這些病也不是這麼容易就可以得到,但,真的讓人覺得恐怖
尤其是腸胃特別差的我,看來是去幾天拉幾天了……
能不能不要去啊啊啊~~~~~~~~~~~~~~~~~~~~~~~!
訂閱:
文章 (Atom)