線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:5688
推到 Plurk!
推到 Facebook!

DBExpress & DataSnap ?!

答題得分者是:GrandRURU
TTS
初階會員


發表:72
回覆:66
積分:27
註冊:2003-05-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-12-24 16:43:37 IP:111.252.xxx.xxx 訂閱
請問 DBExpress & DataSnap功能有何不同?
如果想開發 Multi-Tier 請問與 DBExpress & DataSnap 有何關聯?

PS: for Delphi 2010
編輯記錄
TTS 重新編輯於 2009-12-24 16:45:35, 註解 無‧
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-12-24 16:58:12 IP:203.75.xxx.xxx 未訂閱
DBX 你可以把它想成唯讀的BDE元件

如果要把DBX加上可寫入的方法,就得加上DataSnap來完成

以上的架構就很像早期版本(D3~D5)所講的「BDE / ADO」 「MIDAS」 = Multi-Tier 資料庫程式設計

DBX則是對原本 2-tier (BDE / ADO) 難以改寫為 n-tier 的一種解決方法

又有一說是可以跨平台,但現在看起來只有在Win32平台上比較活躍,可以忽視這點 (笑)

講得太簡單了嗎?
以下是從節錄淺談Borland的資料存取技術

DataSnap
DataSnap原本叫做MIDAS ( Multi-Tier
Distributed Application Services Suite ),是在Delphi
3發展出來,用在多層式架構的應用程式設計環境中,被建置用來讓程式有更好支援性的技術和套件。
DataSnap是Borland特有的資料庫應用程式解決方案,可以讓Delphi和其它的Borland開發工具,將傳統2-tier
( client/server ) 的架構切割成3-tier ( client/applciation server/database
server ) 的架構。
為了讓你更了解DataSnap,下面簡單介紹什麼是1-tier、2-tier和n-tier的資料存取環境。

1-tier
以1-tier的應用系統而言,因為資料存取的來源往往是檔案型式的table files,如果採用BDE來存取這些table files,對於程式本身來說,BDE只是一組被程式載入到記憶體的DLLs而已,對整個系統來說,實際上只有一支程式被執行,這種程式 架構我們便稱之為1-tier。

2-tier
如果一支Delphi程式可以使用BDE ( 或是其他技術 )來存取Server-based資料庫 (例如InterBase、SQL Server或是Oracle),因為資料庫伺服器本身就是一個獨立執行的應用程式,不論存取資料的程式和資料庫伺服器是否同處於同一台機器上,就是一支 2-tier的應用程式,例如程式存取的資料庫是位於同一台機器上的Local InterBase也是一樣,因為LocaInterBase自己就是一個獨立執行的程式。

3-tier ( n-tiered )
一個3-Tier的應用程式是在原來傳統2-tier的架構中,再加入一層middle-tier,這一層稱為 “Application Server”,這一層的角色是在系統中,用來處理資源的集中和資料的分派,在這種三層式架構的應用系統中,資料庫伺服器、中間層的 “Application Server”以及連結中間層的客戶端程式,都是各自獨立的,只是客戶端程式和中間層的“Application Server”必須用DataSnap(MIDAS)來連結,協力完成對後端資料庫伺服器的資料存取。


===================引 用 TTS 文 章===================
請問 DBExpress & DataSnap功能有何不同?
如果想開發 Multi-Tier 請問與 DBExpress & DataSnap 有何關聯?

PS: forDelphi 2010
編輯記錄
GrandRURU 重新編輯於 2009-12-25 13:15:18, 註解 無‧
GrandRURU 重新編輯於 2009-12-25 13:16:45, 註解 無‧
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-12-25 13:36:50 IP:203.75.xxx.xxx 未訂閱
>DBX則是對原本 2-tier (BDE / ADO) 難以改寫為 n-tier 的一種解決方法

針對這個項目再來多說一點好了。

以BDE來說,以往我們在寫1/2 Tier程式時,我們只需要使用到TTable / TQuery等元件即可,但我們如果要延伸變成3 Tier時。我們要怎麼做呢?

首先,我們要做的是「Application server」,而裡面要放的則是原有的TTable / TQuery TDataProvider元件。

再來就是「Client」,要放什麼呢?就是DCOM ClientDataSet。

然後呢?

之後的工作就是把原本屬於TTable / TQuery內的程式碼全部搬到ClientDataSet。就是這個搬移的工作,往往讓設計師痛個半死。

而使用DBX的場合呢?
喝口水,休息一下吧。順便思考一下DBX的架構吧。^ ^
TTS
初階會員


發表:72
回覆:66
積分:27
註冊:2003-05-06

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-12-26 02:40:36 IP:118.170.xxx.xxx 訂閱
真正是全國電子 感恩啦 GrandRURU 大大

也希望能多提供一些觀念及簡單實作!!

=Tks=
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-12-27 09:58:30 IP:118.167.xxx.xxx 未訂閱
這部份你可以參考一下內建提供的example(for MySQL)

網路上的也有
比方說像:http://www.jackforfun.com/2008/11/delphi-2009-dbexpress-unicode-mysql-50.html

Google隨便找有很多。

或是可以買
陳惟彬老師寫的〔Delphi與資料庫開發手札〕(實戰)

李維老師寫的「Delphi 7 高效率資料庫程式設計」(架構理論),這本是繁體,現在也不太好買。簡體是「delphi2006」版,與現在的2010 Dbexpress架構上蠻接近的。

===================引 用 TTS 文 章===================
也希望能多提供一些觀念及簡單實作!!
sryang
尊榮會員


發表:38
回覆:742
積分:876
註冊:2002-06-27

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-10-22 22:58:27 IP:111.254.xxx.xxx 訂閱
我也來講兩句
與 MultiTier 最有關聯的是 DataSnap,AP Server 端用 BDE / dbGo / dbExpress 都可以寫 MultiTier
使用 dbExpress 的好處是輕量化,快速

試想 (以無狀態的 AP Server 來說,有狀態的 AP Server 只是學生交作業的程度):
如果使用 BDE / dbGo 來寫 AP Server,擷取資料後,佔用了一份記憶體用來儲存擷取到的資料,組完 data packet 送到 client 端之後,這份記憶體就沒有作用了
而使用 dbExpress 的話,不需要佔用這份很快會不需要它的記憶體
這可以讓 AP Server 能夠應付更多的 client 請求

所以,有 dbExpress 可用當然應該用
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-10-24 17:00:43 IP:203.75.xxx.xxx 未訂閱
不能認同你更多!

但…關於DBX是無狀態的說明是在哪邊可以看到啊?我找不到的說

===================引 用 sryang 文 章===================
我也來講兩句
與 MultiTier 最有關聯的是 DataSnap,AP Server 端用 BDE / dbGo / dbExpress 都可以寫 MultiTier
使用 dbExpress 的好處是輕量化,快速

試想 (以無狀態的 AP Server 來說,有狀態的 AP Server 只是學生交作業的程度):
如果使用 BDE / dbGo 來寫 AP Server,擷取資料後,佔用了一份記憶體用來儲存擷取到的資料,組完 data packet 送到 client 端之後,這份記憶體就沒有作用了
而使用 dbExpress 的話,不需要佔用這份很快會不需要它的記憶體
這可以讓 AP Server 能夠應付更多的 client 請求

所以,有 dbExpress 可用當然應該用
sryang
尊榮會員


發表:38
回覆:742
積分:876
註冊:2002-06-27

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-10-24 18:19:50 IP:111.254.xxx.xxx 訂閱
我的意思是說,如果要寫無狀態的 AP Server,使用 dbExpress 會比使用 BDE, dbGo 更節省資源

如果 ClientDataSet.PacketRecords 設定為 100 的話,表示一次要從 AP Server 拿 100 筆資料回來
dbExpress 取資料時,只需要1 筆大小的記憶體
而 BDE, dbGo 都至少需要 100 筆大小的記憶體 (如果分批查詢的 SQL 沒有做好,會需要更多記憶體)

而這些佔用的記憶體,在 DataSetProvider 處理完 data packet 的包裝之後,就沒有用了

所以,如果要寫無狀態的 AP Server,有 dbExpress 能用當然要用


因為 dbExpress 不會保存擷取過的資料,所以 dbExpress 沒有辦法修改擷取下來的資料
必須把資料經過 DataSetProvider 倒進 ClientDataSet,由 ClientDataSet 負責儲存擷取下來的資料
所有新增/修改/刪除擷取下來資料的動作,都由 ClientDataSet 來處理

等到 ClientDataSet.ApplyUpdates() 時,由 DataSetProvider 呼叫 DataSetResolver (這是 DataSnap 的一部分) 產生更新資料用的 SQL 敘述
交由 dbExpress 去執行,最後完成更新後端資料的工作

也就是說,使用 dbExpress 撰寫 2-Tier 的程式,跟撰寫 3-Tier 的程式使用到的元件跟技巧都是一樣的
不過,Delphi 為了體恤程式開發人員,特別提供了 TSimpleDataSet 以作為單純的擷取資料使用
TSimpleDataSet = TSQLDataSet TDataSetProvider TClientDataSet
乍看之下很好用,但是用途很受限制
1. 無法藉由修改 TField.ProviderFlags 來控制這個欄位要不要 InKey、InWhere、InUpdate
2. Join Table 的狀況時,組出來的更新 SQL 一定是錯誤的,所以 Join Table 只能查詢
3. 單一資料表才可以新增/更正/刪除/查詢

先講到這邊吧,如果大家有興趣我再接下去

------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
編輯記錄
sryang 重新編輯於 2010-10-24 04:40:25, 註解 無‧
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2010-10-25 01:26:55 IP:111.249.xxx.xxx 未訂閱
DBX還是好用,我只能這樣說

我還是有點疑惑

===================引 用 sryang 文 章===================
..43..
因為 dbExpress 不會保存擷取過的資料,所以 dbExpress 沒有辦法修改擷取下來的資料
必須把資料經過 DataSetProvider 倒進 ClientDataSet,由 ClientDataSet 負責儲存擷取下來的資料
所有新增/修改/刪除擷取下來資料的動作,都由 ClientDataSet 來處理
==>只剩下FIRST, NEXT, LAST的DBX,頗有神鵰大俠楊過的味道

等到 ClientDataSet.ApplyUpdates() 時,由 DataSetProvider 呼叫 DataSetResolver (這是 DataSnap 的一部分) 產生更新資料用的 SQL 敘述
交由 dbExpress 去執行,最後完成更新後端資料的工作
==>補充:產生的SQL是直接交給DBConnection (Ex. TSQLConnection, TDatabase, TADOConnection...etc)來處理。

也就是說,使用 dbExpress 撰寫 2-Tier 的程式,跟撰寫 3-Tier 的程式使用到的元件跟技巧都是一樣的
不過,Delphi 為了體恤程式開發人員,特別提供了 TSimpleDataSet 以作為單純的擷取資料使用
TSimpleDataSet = TSQLDataSet TDataSetProvider TClientDataSet
乍看之下很好用,但是用途很受限制
1. 無法藉由修改 TField.ProviderFlags 來控制這個欄位要不要 InKey、InWhere、InUpdate
2. Join Table 的狀況時,組出來的更新 SQL 一定是錯誤的,所以 Join Table 只能查詢
3. 單一資料表才可以新增/更正/刪除/查詢
==>2和3就算是用標準元件處理也會發生同樣狀況,要JOIN的話還是用兩組DBX元件處理比較穩當
另外,在Delphi6 / BCB6下的名稱是TSQLClientDataSet,是在C語言架構下產生的一個元件,後來因為效能不佳而改用原生Pascal語言重寫成為TSimpleDataSet
(摘自[Delphi 2006 高效數據庫程式設計 -- 使用dbExpress]一書)

先講到這邊吧,如果大家有興趣我再接下去
==>那我就先搬沙發坐下了 XD
有沒有免費的飲料可以喝?
編輯記錄
GrandRURU 重新編輯於 2010-10-24 11:33:58, 註解 無‧
sryang
尊榮會員


發表:38
回覆:742
積分:876
註冊:2002-06-27

發送簡訊給我
#10 引用回覆 回覆 發表時間:2010-10-25 08:27:58 IP:111.254.xxx.xxx 訂閱
上期說到的一個屬性:TField.ProviderFlags,這對於組 SQL 來說至關重要!

ProviderFlags 是 TProviderFlag 的集合,我們來看看 ProviderFlags 可以包含哪些元素
元素名稱說明 備註
pfInUpdateINSERT / UPDATE 要包含此欄位實際上會不會包含,要看欄位值有沒有變動而定
pfInWhereUPDATE / DELETE 時要加入 WHERE實際上會不會加入 WHERE,要看欄位值有沒有變動而定
pfInKeyUPDATE / DELETE 時要加入 WHERE,以及 DataSet 內資料的重複檢查一定會加入WHERE
pfHidden隱藏欄位,僅作為保存資料用途,避免資料衝突,外界無法使用

另外,還有一個跟組 SQL 有關的重要屬性:TDataSetProvider.UpdateMode
屬性值說明
upWhereAll所有欄位均會加入 WHERE
upWhereChanged(有變動,且有 pfInWhere 的欄位) OR (有 pfInKey 的欄位),會加入 WHERE
upWhereKeyOnly只有 pfInKey 的欄位會加入 WHERE

這兩個屬性決定了組 SQL 的結果
例如:select A.A1, A.A2, A.A3, B.B4 from TABLE_1 A inner join TABLE_2 B on A.A1=B.B1
有四個欄位 A1, A2, A3, B4,A1 是 A 的 PK
但是更新時只要更新 A 的欄位,不要更新 B 的欄位

如果完全依照預設值,各欄位的 ProviderFlags 都是 [pfInUpdate, pfInWhere]
DataSetProvider.UpdateMode 為 upWhereAll
當 UPDATE 時,B4 會組進 SQL,但 B4 並不是 A 的欄位,所以會發生錯誤

於是 ProviderFlags 的設法應該為:
A1 = [pfInKey, pfInUpdate]
A2 = [pfInUpdate]
A3 = [pfInUpdate]
B4 = []
而且 DataSetProvider.UpdateMode 設為 upWhereKeyOnly
這樣 B4 就不會加入 UPDATE 的 SQL,就 OK 了

不管 JOIN 幾個 TABLE,設定 ProviderFlags 的原則為
主檔 PK 欄位要有 pfInKey
主檔需要 UPDATE 的欄位要有 pfInUpdate
主檔不需要 UPDATE 的欄位,以及所有 JOIN 進來的欄位就給他 空集合

以上 ProviderFlags 要設定在 TSQLQuery / TSQLDataSet 裡面的 Field 才有效,設定在 TClientDataSet 裡面的 Field 無效
(就是要設定在 DataSetProvider.DataSet 指到的 DataSet 裡面的 Field 才行)

而 TSimpleDataSet 因為是繼承 TClientDataSet,所以裡面的 Field 其實是 TClientDataSet 裡面的 Field
所以上一期才說「TSimpleDataSet 無法藉由修改 TField.ProviderFlags 來控制這個欄位要不要 InKey、InWhere、InUpdate」
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
編輯記錄
sryang 重新編輯於 2010-10-24 18:29:31, 註解 無‧
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#11 引用回覆 回覆 發表時間:2010-10-26 08:23:07 IP:203.75.xxx.xxx 未訂閱
謝謝Sryang大 精闢的解說
之前對於join的更新都採用自訂的Update語法處理,現在可以試著用ProviderFlags來處理了

===================引 用 sryang 文 章===================
上期說到的一個屬性:TField.ProviderFlags,這對於組 SQL 來說至關重要!

ProviderFlags 是 TProviderFlag 的集合,我們來看看 ProviderFlags 可以包含哪些元素
元素名稱說明備註
pfInUpdateINSERT / UPDATE 要包含此欄位實際上會不會包含,要看欄位值有沒有變動而定
pfInWhereUPDATE / DELETE 時要加入 WHERE實際上會不會加入 WHERE,要看欄位值有沒有變動而定
pfInKeyUPDATE / DELETE 時要加入 WHERE,以及 DataSet 內資料的重複檢查一定會加入WHERE
pfHidden隱藏欄位,僅作為保存資料用途,避免資料衝突,外界無法使用

另外,還有一個跟組 SQL 有關的重要屬性:TDataSetProvider.UpdateMode
屬性值說明
upWhereAll所有欄位均會加入 WHERE
upWhereChanged(有變動,且有 pfInWhere 的欄位) OR (有 pfInKey 的欄位),會加入 WHERE
upWhereKeyOnly只有 pfInKey 的欄位會加入 WHERE

這兩個屬性決定了組 SQL 的結果
例如:select A.A1, A.A2, A.A3, B.B4 from TABLE_1 A inner join TABLE_2 B on A.A1=B.B1
有四個欄位 A1, A2, A3, B4,A1 是 A 的 PK
但是更新時只要更新 A 的欄位,不要更新 B 的欄位

如果完全依照預設值,各欄位的 ProviderFlags 都是 [pfInUpdate, pfInWhere]
DataSetProvider.UpdateMode 為 upWhereAll
當 UPDATE 時,B4 會組進 SQL,但 B4 並不是 A 的欄位,所以會發生錯誤

於是 ProviderFlags 的設法應該為:
A1 = [pfInKey, pfInUpdate]
A2 = [pfInUpdate]
A3 = [pfInUpdate]
B4 = []
而且 DataSetProvider.UpdateMode 設為 upWhereKeyOnly
這樣 B4 就不會加入 UPDATE 的 SQL,就 OK 了

不管 JOIN 幾個 TABLE,設定 ProviderFlags 的原則為
主檔 PK 欄位要有 pfInKey
主檔需要 UPDATE 的欄位要有 pfInUpdate
主檔不需要 UPDATE 的欄位,以及所有 JOIN 進來的欄位就給他 空集合

以上 ProviderFlags 要設定在 TSQLQuery / TSQLDataSet 裡面的 Field 才有效,設定在 TClientDataSet 裡面的 Field 無效
(就是要設定在 DataSetProvider.DataSet 指到的 DataSet 裡面的 Field 才行)

而 TSimpleDataSet 因為是繼承 TClientDataSet,所以裡面的 Field 其實是 TClientDataSet 裡面的 Field
所以上一期才說「TSimpleDataSet 無法藉由修改 TField.ProviderFlags 來控制這個欄位要不要 InKey、InWhere、InUpdate」
系統時間:2017-12-14 22:54:38
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!