<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    鷹翔宇空

    學習和生活

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks

    引自:http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/SCArchDeGuide/Chapter1Introduction.mspx

    第 2 章 — 處理數(shù)據

    發(fā)布日期: 8/20/2004 | 更新日期: 8/20/2004

    智能客戶端體系結構與設計指南

    David Hill, Brenton Webster, Edward A. Jezierski, Srinath Vasireddy and Mohammad Al-Sabt, Microsoft Corporation; Blaine Wastell, Ascentium Corporation; Jonathan Rasmusson and Paul Gale, ThoughtWorks; and Paul Slater, Wadeware LLC

    相關鏈接

    Microsoft? patterns & practiceshttp://www.microsoft.com/resources/practices/default.mspx

    Application Architecture for .NET: Designing Applications and Serviceshttp://msdn.microsoft.com/library/en-us/dnbda/html/distapp.asp

    摘要:本章分析在客戶端處理數(shù)據時的各種注意事項,包括數(shù)據緩存、數(shù)據并發(fā)以及數(shù)據集和 Windows 窗體數(shù)據綁定的使用。

    *
    本頁內容
    數(shù)據類型 數(shù)據類型
    緩存數(shù)據 緩存數(shù)據
    數(shù)據并發(fā) 數(shù)據并發(fā)
    使用 ADO.NET 數(shù)據集來管理數(shù)據 使用 ADO.NET 數(shù)據集來管理數(shù)據
    Windows 窗體數(shù)據綁定 Windows 窗體數(shù)據綁定
    小結 小結

    在智能客戶端中,可在客戶端上使用應用程序數(shù)據。要使您的智能客戶端有效工作,很重要的一點是對該數(shù)據進行適當?shù)墓芾恚源_保其有效、一致和安全。

    可以通過服務器端應用程序(例如,通過 Web 服務)向客戶端提供應用程序數(shù)據,或者應用程序可以使用它自己的本地數(shù)據。如果數(shù)據是由應用程序提供的,則智能客戶端應用程序可以緩存數(shù)據以改善性能或者支持脫機使用。在這種情況下,您需要決定客戶端應用程序應該如何處理就該服務器而言已經過時的數(shù)據。

    如果智能客戶端應用程序提供在本地修改數(shù)據的能力,則必須在以后將客戶端更改與服務器端應用程序進行同步。在這種情況下,您必須決定客戶端應用程序如何處理數(shù)據沖突,以及如何跟蹤需要發(fā)送到服務器的更改。

    在設計您的智能客戶端應用程序時,您需要認真考慮這些問題以及其他許多問題。本章分析了在客戶端上處理數(shù)據時的各種注意事項,包括:

    ?

    數(shù)據類型。

    ?

    緩存數(shù)據。

    ?

    數(shù)據并發(fā)。

    ?

    使用 ADO.NET 數(shù)據集來管理數(shù)據。

    ?

    Windows 窗體數(shù)據綁定。

    本章未討論其他許多與處理數(shù)據有關的問題。具體說來,在第 5 章:安全性注意事項中討論了數(shù)據處理安全性問題,在第 4 章:偶爾連接的智能客戶端中討論了脫機注意事項。

    數(shù)據類型

    智能客戶端通常必須處理兩種類別的數(shù)據:

    ?

    只讀引用數(shù)據

    ?

    瞬態(tài)數(shù)據

    通常情況下,需要以不同的方式處理這些類型的數(shù)據,因此更詳細地分析一下每種類型將是很有用的。

    只讀引用數(shù)據

    只讀引用數(shù)據是不會由客戶端更改并且被客戶端用于引用目的的數(shù)據。因此,從客戶端的觀點看來,該數(shù)據為只讀數(shù)據,并且客戶端不會對其執(zhí)行更新、插入或刪除操作。只讀引用數(shù)據很容易在客戶端上進行緩存。引用數(shù)據在智能客戶端應用程序中具有許多種用途,包括:

    ?

    提供靜態(tài)引用或查找數(shù)據。這方面的示例包括產品信息、價格表、發(fā)貨選項和價格。

    ?

    支持數(shù)據驗證,允許檢查用戶輸入數(shù)據的正確性。示例有針對交貨時間表檢查輸入的日期。

    ?

    幫助與遠程服務進行通訊。示例在本地將用戶選擇轉化為產品 ID,然后將該信息發(fā)送到 Web 服務。

    ?

    呈現(xiàn)數(shù)據。示例包括呈現(xiàn)幫助文本或用戶界面標簽。

    通過在客戶端上存儲和使用引用數(shù)據,您可以減少需要從客戶端傳輸?shù)椒掌鞯臄?shù)據量,改善應用程序的性能,幫助啟用脫機功能,并提供早期數(shù)據驗證以提高應用程序的可用性。

    盡管客戶端無法更改只讀引用數(shù)據,但可以在服務器上進行更改(例如,由管理員或超級用戶更改)。您需要確定在發(fā)生數(shù)據更改時用于更新客戶端的策略。此類策略可能涉及到在發(fā)生更改時將更改推到客戶端上,或者按照特定的時間間隔或在客戶端上執(zhí)行某些操作之前從服務器拉入更改。但是,因為數(shù)據在客戶端上是只讀的,所以您無須跟蹤客戶端更改。這就簡化了需要對只讀引用數(shù)據進行處理的方式。

    瞬態(tài)數(shù)據

    瞬態(tài)數(shù)據既可以在服務器上更改,也可以在客戶端上更改。通常情況下,瞬態(tài)數(shù)據作為用戶輸入和操作的直接或間接結果而發(fā)生更改。在此情況下,在客戶端或服務器進行的更改都需要在某個時刻進行同步。這種類型的數(shù)據在智能客戶端中具有許多種用途,包括:

    ?

    添加新信息。示例包括添加銀行業(yè)務交易或客戶詳細信息。

    ?

    修改現(xiàn)有信息。示例更新客戶詳細信息。

    ?

    刪除現(xiàn)有信息。示例從數(shù)據庫中刪除客戶。

    在智能客戶端處理瞬態(tài)數(shù)據的最困難的方面之一在于,這些數(shù)據通常可能在多個客戶端上同時進行修改。當數(shù)據非常不穩(wěn)定時,該問題將惡化,因為所做更改更有可能互相沖突。

    您需要跟蹤您對瞬態(tài)數(shù)據進行的任何客戶端更改。在與服務器同步數(shù)據并且已經解決任何沖突之前,您不應該認為瞬態(tài)數(shù)據已被確認。您應該非常小心以避免依賴未確認的數(shù)據進行重要決策,或者在未認真考慮如何保證數(shù)據一致性(甚至在同步失敗時)的情況下使用該數(shù)據作為其他本地更改的基礎。

    有關圍繞脫機時處理數(shù)據的問題以及如何處理數(shù)據同步的詳細信息,請參閱第 4 章:偶爾連接的智能客戶端

    返回頁首返回頁首

    緩存數(shù)據

    智能客戶端通常需要在本地緩存數(shù)據(無論是只讀引用數(shù)據還是瞬態(tài)數(shù)據)。通過緩存數(shù)據,有可能改善應用程序的性能并提供脫機工作所需的數(shù)據。但是,您需要認真考慮在客戶端緩存哪些數(shù)據、如何管理這些數(shù)據以及可以在哪個上下文中使用這些數(shù)據。

    要啟用數(shù)據緩存,您的智能客戶端應用程序應該實現(xiàn)某種形式的緩存基礎結構,以便透明地處理數(shù)據緩存細節(jié)。您的緩存基礎結構應該包括下列緩存機制中的一種或兩種:

    ?

    短期數(shù)據緩存。在內存中緩存數(shù)據對性能有益,但不能持久,因此您可能需要在重新運行應用程序時從源拉入數(shù)據。這樣做可能會妨礙您的應用程序脫機操作。

    ?

    長期數(shù)據緩存。通過在持久性媒體(如獨立存儲或本地文件系統(tǒng))中緩存數(shù)據,可以在沒有連接到服務器時使用應用程序。您可以選擇將長期存儲與短期存儲結合起來以改善性能。

    無論您采用哪種緩存機制,都應該確保僅將用戶有權訪問的數(shù)據提供給客戶端。而且,在客戶端緩存的敏感數(shù)據要求進行認真處理以確保它的安全。因此,您可能需要在將數(shù)據傳輸?shù)娇蛻舳艘约霸诳蛻舳舜鎯?shù)據時,對數(shù)據進行加密。有關詳細信息,請參閱第 5 章:安全性注意事項中的“處理敏感數(shù)據”。

    當您設計智能客戶端以支持數(shù)據緩存時,您應該考慮為客戶端提供一種請求新數(shù)據的機制,而無論緩存的狀態(tài)如何。這意味著您可以確保應用程序隨時能夠執(zhí)行新的事務,并且不會使用過時的數(shù)據。您還可以將客戶端配置為預先獲取數(shù)據,以便減少在緩存數(shù)據到期時處于脫機狀態(tài)的風險。

    只要有可能,您都應該將某種形式的元數(shù)據與該數(shù)據關聯(lián)起來,以便使客戶端能夠以聰明的方式管理這些數(shù)據。此類元數(shù)據可用于指定數(shù)據的標識和任何約束,或者指定所需的與該數(shù)據關聯(lián)的行為。您的客戶端緩存基礎結構應該消耗該元數(shù)據,并且使用它來適當處理緩存的數(shù)據。

    客戶端緩存的所有數(shù)據都應該是可以唯一標識的(例如,通過版本號或日期戳),以便在確定是否需要更新數(shù)據時,可以正確地識別相應的數(shù)據。這樣,您的緩存基礎結構就能夠詢問服務器它所具有的數(shù)據當前是否有效,并且確定是否需要進行更新。

    元數(shù)據還可以用來指定與緩存數(shù)據的使用和處理相關的約束或行為。示例包括:

    ?

    時間約束。這些約束指定可以使用緩存數(shù)據的時間或日期范圍。當該數(shù)據過時或到期時,可以將其從緩存中丟棄,或者通過從服務器獲取最新數(shù)據來自動刷新數(shù)據。在某些情況下,合適的做法可能是讓客戶端使用過時的引用數(shù)據,并且在與服務器進行同步時將過時數(shù)據映射到最新數(shù)據。

    ?

    地理約束。某些數(shù)據可能僅適用于特定地區(qū)。例如,您可能對于不同的地點有不同的價格表。可以使用您的緩存基礎結構分別針對不同的地點來訪問和存儲數(shù)據。

    ?

    安全性要求。可以將專門提供給特定用戶的數(shù)據加密,以確保只有相應的用戶可以訪問這些數(shù)據。在此情況下,所提供的數(shù)據已經進行了加密,并且用戶必須向緩存基礎結構提供憑據以便對數(shù)據進行解密。

    ?

    業(yè)務規(guī)則。您可能擁有與緩存數(shù)據關聯(lián)的業(yè)務規(guī)則,用來規(guī)定如何使用這些數(shù)據。例如,您的緩存基礎結構可能考慮用戶的角色,以便確定向該用戶提供哪些數(shù)據以及如何處理這些數(shù)據。

    您的緩存基礎結構可以通過與數(shù)據關聯(lián)的元數(shù)據來適當?shù)靥幚磉@些數(shù)據,從而使您的應用程序無須關心數(shù)據緩存問題或實現(xiàn)細節(jié)。您可以在引用數(shù)據本身內部傳遞與這些數(shù)據關聯(lián)的元數(shù)據,或者您可以使用帶外機制。用于將元數(shù)據傳輸?shù)娇蛻舳说拇_切機制取決于您的應用程序與網絡服務的通訊方式。當使用 Web 服務時,利用 SOAP 頭將元數(shù)據傳輸?shù)娇蛻舳耸且环N很好的解決方案。

    只讀引用數(shù)據與瞬態(tài)數(shù)據之間存在的區(qū)別有時意味著您需要使用兩個緩存,一個用于引用數(shù)據,一個用于瞬態(tài)數(shù)據。引用數(shù)據在客戶端是只讀的,并且不需要回過頭來與服務器進行同步,但它的確需要偶爾進行刷新以反映在服務器上進行的任何更改和更新。

    瞬態(tài)數(shù)據既可以在服務器上更改,也可以在客戶端上更改。既然有時在客戶端更新緩存中的數(shù)據,有時在服務器更新,有時在這兩個位置更新,那么對客戶端數(shù)據進行的更改需要在某個時刻與服務器進行同步。如果數(shù)據同時在服務器上發(fā)生了更改,則會發(fā)生數(shù)據沖突,需要對其進行適當?shù)奶幚怼?/P>

    要幫助確保維持數(shù)據一致性,并且避免不適當?shù)厥褂脭?shù)據,您應該小心地跟蹤您在客戶端對瞬態(tài)數(shù)據進行的任何更改。在成功地與服務器進行同步或確認之前,此類更改是未提交的 或暫定的。

    您應該對您的智能客戶端應用程序進行適當?shù)脑O計,以使其能夠區(qū)分已經成功地與服務器進行同步的數(shù)據和仍然暫定的數(shù)據。這一區(qū)分過程可以幫助應用程序更加容易地檢測和處理數(shù)據沖突。而且,您可能需要禁止應用程序或用戶基于暫定數(shù)據進行重要決策或者啟動重要操作。在將此類數(shù)據與服務器進行同步之前,不應該依賴它們。通過使用適當?shù)木彺婊A結構,可以跟蹤暫定數(shù)據和已經確認的數(shù)據。

    緩存應用程序塊(Caching Application Block)

    緩存應用程序塊是一個 Microsoft? .NET 框架擴展,它使開發(fā)人員可以容易地緩存來自服務提供程序的數(shù)據。生成和設計它的目的是將 Microsoft 建議的緩存準則封裝在 .NET 框架應用程序中,如位于 http://msdn.microsoft.com/library/en-us/dnbda/html/CachingArch.asp 的 Caching Architecture Guide for .NET Framework Applicationss 所述。

    緩存塊的總體體系結構如圖 2.1 所示。


    2.1 緩存塊工作流

    緩存工作流包含下列步驟:

    1.

    客戶端或服務代理向 CacheManager 發(fā)出對緩存數(shù)據項的請求。

    2.

    如果該數(shù)據項已被緩存,則 CacheManager 會從存儲中檢索該項,并將其作為 CacheItem 對象返回。如果該項尚未緩存,則會通知客戶端。

    3.

    在從服務提供程序檢索未緩存的數(shù)據之后,客戶端將該數(shù)據發(fā)送給 CacheManagerCacheManager 會將一個簽名(即,元數(shù)據)如密鑰、到期時間或優(yōu)先級等添加到該數(shù)據項中,并將其加載到緩存中。

    4.

    CacheService 監(jiān)控 CacheItems 的生存期。當 CacheItem 到期時,CacheService 會刪除它并根據情況調用回調委托。

    5.

    CacheService 還可以將所有數(shù)據項從緩存中清除出去。

    緩存塊提供了多種緩存到期選項,如表 2.1 所述。

    2.1 緩存塊到期選項

    說明

    AbsoluteTime

    用于設置到期時間的絕對時間。

    ExtendedFormatTime

    用于基于表達式(如 every minute 或 every Monday)設置到期時間。

    FileDependency

    用于基于文件是否更改來設置到期時間。

    SlidingTime

    用于設置項的生存期,方法是基于項的上次訪問時間來指定到期時間。

    下列存儲機制可供緩存塊使用:

    ?

    內存映射文件 (MMF)。MMF 最適合于基于客戶端的高性能緩存方案。您可以使用 MMF 來開發(fā)可在同一臺計算機中的多個應用程序域和進程之間共享的緩存。.NET 框架不支持 MMF,因此 MMF 緩存的任何實現(xiàn)都以非托管代碼的形式運行,并且不會從任何 .NET 框架功能中受益,包括內存管理功能(如垃圾回收)和安全性功能(如代碼訪問安全性)。

    ?

    Singleton 對象。可以使用 .NET 遠程處理 singleton 對象來緩存可在一臺或多臺計算機中的進程之間共享的數(shù)據。方法是使用通過 .NET 遠程處理為多個客戶端提供服務的 singleton 對象來實現(xiàn)緩存服務。單例緩存的實現(xiàn)很簡單,但它缺乏基于 Microsoft SQL Server? 的解決方案所提供的性能和可伸縮性。

    ?

    Microsoft SQL Server 2000 數(shù)據庫。SQL Server 2000 存儲最適合于應用程序要求具有高持續(xù)性或者您需要緩存大量數(shù)據的場合。因為緩存服務需要通過網絡訪問 SQL Server,并且使用數(shù)據庫查詢檢索數(shù)據,所以數(shù)據訪問的速度相對比較慢。

    ?

    Microsoft SQL Server 桌面引擎 (MSDE)。MSDE 是 SQL Server 2000 的輕型數(shù)據庫替代產品。它提供了可靠性和安全性功能,但具有比 SQL Server 更小的客戶端足跡,因此它需要較少的設置和配置。因為 MSDE 支持 SQL,所以開發(fā)人員可以得到數(shù)據庫的很多功能。如有必要,您可以將 MSDE 數(shù)據庫遷移到 SQL Server 數(shù)據庫。

    返回頁首返回頁首

    數(shù)據并發(fā)

    正如前面所提到的,使用智能客戶端的一個問題是:在將任何客戶端更改與服務器進行同步之前,服務器上保存的數(shù)據可能發(fā)生更改。您需要采用某種機制來確保在對數(shù)據進行同步時,數(shù)據沖突能夠得到適當?shù)奶幚恚⑶易詈蟮玫降臄?shù)據是一致和正確的。數(shù)據能夠由多個客戶端進行更新的能力稱為“數(shù)據并發(fā)”。

    您可以使用兩種方法來處理數(shù)據并發(fā):

    ?

    保守式并發(fā)。保守式并發(fā)允許一個客戶端保持數(shù)據上的鎖,以禁止任何其他客戶端修改數(shù)據,直至客戶端自己的更改完成為止。在這種情況下,如果另一個客戶端嘗試修改數(shù)據,則在鎖的擁有者釋放該鎖之前,這些嘗試將失敗或者被阻止。

    ?

    保守式并發(fā)可能有問題,因為單個用戶或客戶端可能由于疏忽而長時間地保持鎖定。所以,該鎖可能會妨礙重要資源(如數(shù)據庫行或文件)及時得到釋放,從而嚴重影響應用程序的可伸縮性和可用性。但是,當您需要完全控制對重要資源所做的更改時,保守式并發(fā)可能是適當?shù)摹U堊⒁猓绻目蛻舳艘摍C工作,則不能使用這種并發(fā),因為客戶端無法對數(shù)據加鎖。

    ?

    開放式并發(fā)。開放式并發(fā)不會鎖定數(shù)據。要判斷是否實際需要更新,可以將原始數(shù)據隨更新請求和已更改的數(shù)據一起發(fā)送。隨后,將針對當前數(shù)據檢查原始數(shù)據,以查看是否同時對原始數(shù)據進行了更新。如果原始數(shù)據和當前數(shù)據匹配,則執(zhí)行更新;否則,拒絕請求,并產生開放式失敗。要優(yōu)化該過程,您可以在數(shù)據中使用時間戳或更新計數(shù)器,而不必發(fā)送原始數(shù)據,此時只需要檢查時間戳或計數(shù)器。

    開放式并發(fā)提供了一種良好的機制,可用來更新不會非常頻繁更改的主數(shù)據,如客戶的電話號碼或地址。開放式并發(fā)允許每個人讀取數(shù)據,在發(fā)生更新的概率小于讀取操作的情況下,開放式失敗的風險或許是可以接受的。在數(shù)據頻繁更改以及開放式更新可能經常失敗的情況下,開放式并發(fā)可能并不適合。

    在大多數(shù)智能客戶端方案(包括客戶端將要脫機工作的方案)中,開放式并發(fā)是正確的方法,因為它允許多個客戶端同時使用數(shù)據,而不會不必要地鎖定數(shù)據和影響所有其他客戶端。

    有關開放式和保守式并發(fā)的詳細信息,請參閱 .NET Framework Developer's Guide 中的“Optimistic Concurrency”,網址為:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconoptimisticconcurrency.asp

    返回頁首返回頁首

    使用 ADO.NET 數(shù)據集來管理數(shù)據

    DataSet 是一個表示一個或多個關系數(shù)據庫表的對象。數(shù)據集在斷開連接的緩存中存儲數(shù)據。DataSets的結構與關系數(shù)據庫類似:它公開了一個由表、行和列組成的層次結構對象模型。另外,它還包含為DataSets定義的約束和關系。

    ADO.NET DataSet 包含零個或更多個由 DataTable 對象表示的表組成的集合。DataTableSystem.Data 命名空間中定義,并且表示單個由內存駐留數(shù)據組成的表。它包含由 DataColumnCollection 表示的列和由 ConstraintCollection 表示的約束組成的集合,它們共同定義了該表的架構。DataTable 還包含由 DataRowCollection(它包含該表中的數(shù)據)表示的行組成的集合。與其當前狀態(tài)一起,DataRow 保留其當前版本和原始版本,以便標識對該行中存儲的值所做的更改。

    DataSets可以強類型化或非類型化。類型化的 DataSetDataSet 基類繼承,但是向 DataSet 中添加了強類型化的語言功能,從而使用戶可以用更加強類型化的編程方式訪問內容。在生成應用程序時,可以使用任一種類型。但是,Microsoft Visual Studio ? 開發(fā)系統(tǒng)對類型化DataSets具有更多支持,它們使得用DataSets編程變得更加容易,而且更不容易出錯。

    DataSets在智能客戶端環(huán)境中尤其有用,因為它們提供了能夠幫助客戶端在脫機狀態(tài)下使用數(shù)據的功能。它們可以跟蹤對數(shù)據進行的本地更改,這有助于與服務器同步數(shù)據以及協(xié)調數(shù)據沖突,并且它們還可用于合并來自不同源的數(shù)據。

    有關如何使用DataSets的詳細信息,請參閱 Visual Basic and Visual C# Concepts 中的“Introduction to DataSets”,網址為:http://msdn.microsoft.com/library/en-us/vbcon/html/vbconDataSets.asp

    用DataSets合并數(shù)據

    DataSets具有將 DataSetDataTableDataRow 對象的內容合并到現(xiàn)有DataSets的能力。對于跟蹤在客戶端上進行的更改以及與服務器的已更新內容進行合并而言,該功能尤其有用。圖 2.2 顯示了一個從 Web 服務請求更新的智能客戶端,新數(shù)據作為數(shù)據傳輸對象 (DTO) 返回。DTO 是一種企業(yè)模式,它使您可以將所有需要與 Web 服務進行通訊的數(shù)據打包到一個對象中。使用 DTO 通常意味著您可以對 Web 服務進行單個調用而不是多個調用。


    2.2 通過使用DataSets合并客戶端上的數(shù)據

    在該示例中,當 DTO 被返回到客戶端時,該 DTO 將被用于在客戶端上以本地方式創(chuàng)建一個新的DataSets。

    在合并操作之后,ADO.NET 不會自動將行狀態(tài)從 modified 更改為 unchanged。因此,在將新的DataSets與本地客戶端DataSets合并之后,您需要調用DataSets上的 AccceptChanges 方法,將 RowState 屬性重置為 unchanged。

    有關如何使用DataSets的詳細信息,請參閱 .NET Framework Developer's Guide 中的“Merging DataSet Contents”,網址為:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconmergingDataSetcontents.asp。

    提高DataSets的性能

    DataSets通常可以包含大量數(shù)據,如果通過網絡傳遞這些數(shù)據,則可能導致性能問題。幸而,通過 ADO.NET DataSets,您可以使用DataSets上的 GetChanges 方法來確保只在客戶端和服務器之間傳送在DataSets中更改過的數(shù)據,并且將該數(shù)據打包到 DTO 中。該數(shù)據隨后將被合并到其目的地的DataSets中。

    圖 2.3 顯示了一個智能客戶端,它對本地數(shù)據進行更改,并且使用DataSets上的 GetChanges 方法僅將已更改的數(shù)據提交給服務器。出于性能原因,該數(shù)據被傳輸給 DTO。


    2.3 使用 DTO 改善性能

    可以將 GetChanges 方法用于需要脫機工作的智能客戶端應用程序。當應用程序重新聯(lián)機時,您可以使用 GetChanges 方法確定哪些信息已經更改,并且隨后生成一個與 Web 服務通訊的 DTO,以便確保將更改提交給數(shù)據庫。

    返回頁首返回頁首

    Windows 窗體數(shù)據綁定

    通過 Windows 窗體數(shù)據綁定,您可以將應用程序的用戶界面連接到該應用程序的基礎數(shù)據。Windows 窗體數(shù)據綁定支持雙向綁定,因此您可以將數(shù)據結構綁定到用戶界面,向用戶顯示當前數(shù)據值,使用戶可以編輯數(shù)據,然后使用用戶輸入的值自動更新基礎數(shù)據。

    您可以使用 Windows 窗體數(shù)據綁定將幾乎任何數(shù)據結構或對象綁定到用戶界面控件的任何屬性。您可以將單個數(shù)據項綁定到控件的單個屬性,還可以將更為復雜的數(shù)據(例如,數(shù)據項集合或數(shù)據庫表)綁定到該控件,以便它可以在數(shù)據網格或列表框中顯示所有數(shù)據。

    您可以綁定任何支持一個或多個公共屬性的對象。您只能綁定到類的公共屬性而不是公共成員。

    通過 Windows 窗體數(shù)據綁定,您可以隨您的應用程序一起提供靈活的、數(shù)據驅動的用戶界面。您可以使用數(shù)據綁定提供對用戶界面外觀的自定義控制(例如,通過綁定到某些控件屬性,如背景或前景顏色、大小、圖像或圖標)。

    數(shù)據綁定具有許多種用途。例如,可以使用它完成下列任務:

    ?

    向用戶顯示只讀數(shù)據。

    ?

    使用戶可以從用戶界面更新數(shù)據。

    ?

    提供數(shù)據上的主從視圖。

    ?

    使用戶可以瀏覽復雜的相關數(shù)據項。

    ?

    提供查找表功能,使用戶界面可以連接用戶友好的顯示名稱。

    本節(jié)分析數(shù)據綁定的一些功能,并討論一些您經常需要在智能客戶端應用程序中實現(xiàn)的數(shù)據綁定功能。

    有關數(shù)據綁定的詳細信息,請參閱“Windows Forms Data Binding and Objects”,網址為:http://msdn.microsoft.com/library/en-us/dnadvnet/html/vbnet02252003.asp

    Windows 窗體數(shù)據綁定體系結構

    Windows 窗體數(shù)據綁定提供了一種用于將數(shù)據雙向連接到用戶界面的靈活的基礎結構。圖 2.4 顯示了 Windows 窗體數(shù)據綁定的總體體系結構的示意圖。


    2.4 Windows 窗體數(shù)據綁定的體系結構

    Windows 窗體數(shù)據綁定使用下列對象:

    ?

    數(shù)據源。數(shù)據源是包含要綁定到用戶界面的數(shù)據的對象。數(shù)據提供程序可以是任何具有公共屬性的對象,可以是支持 IList 接口的數(shù)組或集合,還可以是復雜數(shù)據類(例如,DataSet 或 DataTable)的實例。

    ?

    CurrencyManagerCurrencyManager 對象用于跟蹤綁定到用戶界面的數(shù)組、集合或表內的數(shù)據的當前位置。通過 CurrencyManager 可以將數(shù)據集合綁定到用戶界面以及在相應的數(shù)據中導航,同時更新用戶界面以反映集合內當前選擇的項。

    ?

    PropertyManagerPropertyManager 對象負責維護綁定到控件的對象的當前屬性。PropertyManager 類和 CurrencyManager 類都從公用基類 BindingManagerBase 中繼承。所有綁定到控件的數(shù)據提供程序都具有一個關聯(lián)的 CurrencyManagerPropertyManager 對象。

    ?

    BindingContext。每個 Windows 窗體都具有一個默認的 BindingContext 對象,該對象跟蹤相應窗體上的所有 CurrencyManagerPropertyManager 對象。通過 BindingContext 對象可以容易地檢索特定數(shù)據源的 CurrencyManagerPropertyManager 對象。您可以將特定的 BindingContext 對象分配給包含數(shù)據綁定控件的容器控件(如 GroupBoxPanelTabControl)。這樣做可以使窗體的每個部分都由它自己的 CurrencyManagerPropertyManager 對象管理。

    ?

    BindingBinding 對象用于在控件的單個屬性與另一個對象的屬性或某個對象列表中當前對象的屬性之間創(chuàng)建和維護簡單綁定。

    將數(shù)據綁定到 Windows 窗體控件

    有許多可用于綁定到特定 Windows 窗體控件的屬性和方法。表 2.2 顯示了其中一些比較重要的屬性和方法。

    2.2 用于綁定到 Windows 窗體控件的屬性和方法

    屬性或方法 Windows 窗體控件 說明

    DataSource 屬性

    ListControls(例如,ListBox 或 Combo Box)、

    DataGrid 控件

    使您可以指定要綁定到用戶界面控件的數(shù)據提供程序對象。

    DisplayMember 屬性

    ListControls

    使您可以指定要顯示給用戶的數(shù)據提供程序的成員。

    ValueMember 屬性

    ListControls

    使您可以指定與顯示值相關聯(lián)的、供您的應用程序內部使用的值。

    DataMember 屬性

    DataGrid 控件

    如果數(shù)據源包含多個數(shù)據源(例如,如果您指定了包含多個表的DataSets),請使用 DataMember 屬性來指定要綁定到網格的數(shù)據源。(參閱表后面的備注。)

    SetDataBinding 方法

    DataGrid 控件

    使您可以在運行時重置 DataSource 方法。

    如果 DataSourceDataTableDataView、集合或數(shù)組,則無須設置 DataMember 屬性。

    您還可以使用所有 Windows 窗體控件對象上提供的 DataBindings 集合屬性將 Binding 對象顯式添加到任何控件對象。Binding 對象用于將控件上的單個屬性綁定到數(shù)據提供程序的單個數(shù)據成員。下面的代碼示例在一個文本框控件的 Text 屬性和一個數(shù)據集的 customers 表中的客戶名稱之間添加了綁定。

    textBox1.DataBindings.Add( 
            new Binding( "Text", DataSet, "customers.customerName" ) ); 
    

    當您用 Binding 構造函數(shù)構建 Binding 示例時,您必須指定要綁定到的控件屬性的名稱、數(shù)據源以及可解析為該數(shù)據源中的列表或屬性的導航路徑。該導航路徑可以是空字符串、單個屬性名或句點分隔的名稱層次結構。您可以使用分層的導航路徑在 DataSet 對象中的數(shù)據表和關系中導航,或者在對象的屬性向其他對象返回實例的對象模型中導航。如果您將導航路徑設置為空字符串,則會在基礎數(shù)據源對象上調用 ToString 方法。

    如果屬性是只讀的(即,對象不支持對該屬性進行的設置操作),則數(shù)據綁定默認情況下不會使綁定的 Windows 窗體控件成為只讀的。這可能給用戶帶來混亂,因為用戶可以編輯用戶界面中的值,但綁定對象中的值將不會得到更新。所以,請確保將所有被綁定到只讀屬性的 Windows 窗體控件的只讀標志設置為 true

    將控件綁定到DataSets

    將控件綁定到數(shù)據集通常是有用的。這樣做使您可以在數(shù)據網格中顯示數(shù)據集數(shù)據,并且使用戶可以容易地更新數(shù)據。您可以使用以下代碼將數(shù)據網格控件綁定到 DataSet

    DataSet newDataSet = webServiceProxy.GetDataSet(); 
    this.DataGrid.SetDataBinding( newDataSet, "tableName" ); 
    

    有時,在已經建立與您的控件的所有綁定之后,您需要替換數(shù)據集的內容。但是,在用新的集合替換現(xiàn)有集合時,所有綁定仍將指向舊的數(shù)據集。

    比用新的數(shù)據源手動重新創(chuàng)建數(shù)據綁定更好的辦法是,您可以使用 DataSet 類的 Merge 方法將新數(shù)據集中的數(shù)據導入現(xiàn)有數(shù)據集,如下面的代碼示例所示。

    DataSet newDataSet = myService.GetDataSet(); 
    this.DataSet1.Clear();    
    this.DataSet1.Merge( newDataSet ); 
    

    要避免線程化問題,您應該只在 UI 線程上更新綁定的數(shù)據對象。有關詳細信息,請參閱第 6 章:使用多個線程

    在數(shù)據集合中導航

    如果您的數(shù)據源包含項集合,則可以將該數(shù)據集合綁定到 Windows 窗體控件,并且在該數(shù)據集合中逐項導航。用戶界面將自動更新以反映集合中的當前項。

    您可以綁定到任何支持 IList 接口的集合對象。當您綁定到對象集合時,您可以讓用戶導航該集合中的每個項,并自動更新每個項的用戶界面。.NET Framework 提供的許多集合和復雜數(shù)據類已經支持 IList 接口,因此您可以容易地綁定到數(shù)組或復雜數(shù)據,如數(shù)據行或數(shù)據視圖。例如,任何作為 System.Array 類的實例的數(shù)組對象默認情況下都實現(xiàn)了 IList 接口,因而可以綁定到用戶界面。許多 ADO.NET 對象還支持 IList 接口或它的派生接口,從而使這些對象也可以容易地綁定。例如,DataViewManagerDataSetDataTableDataViewDataColumn 類都以這種方式支持數(shù)據綁定。

    實現(xiàn)了 IList 接口的數(shù)據源由 CurrencyManager 對象管理。該對象通過它的 Position 屬性維護數(shù)據集合的索引。該索引用于確保綁定到該數(shù)據源的所有控件都讀/寫數(shù)據集合中的相同項。

    如果您的窗體包含綁定到多個數(shù)據源的控件,則它將具有多個 CurrencyManager 對象,分別對應于各個獨立的數(shù)據源。BindingContext 對象提供對該窗體上的所有 CurrencyManager 對象的方便訪問。下面的代碼示例顯示了如何在 customers 集合內部遞增當前位置。

    this.BindingContext[ DataSet, "customers" ].Position += 1; 
    

    您應該像以下代碼示例中所示的那樣,使用 CurrencyManager 對象上的 Count 屬性來確保不會設置無效位置。

    if ( this.BindingContext[ DataSet, "customer" ].Position < 
         ( this.BindingContext[ DataSet, "customer" ].Count – 1 ) ) 
    { 
        this.BindingContext[ DataSet, "customers" ].Position += 1; 
    } 
    

    CurrencyManager 對象還支持 PositionChanged 事件。您可以創(chuàng)建該事件的處理程序,以便更新您的用戶界面以反映當前綁定位置。下面的代碼示例顯示了一個標簽,以說明當前位置和記錄總數(shù)。

    this.BindingContext[ DataSet, "customers" ].PositionChanged += 
            new EventHandler( this.BindingPositionChanged ); 
    

    方法 BindingPositionChanged 的實現(xiàn)方式如下所示。

    private void BindingPositionChanged( object sender, System.EventArgs e ) 
    {    
        positionLabel.Text = string.Format( "Record {0} of {1}", 
            this.BindingContext[dsPubs1, "authors"].Position + 1,  
            this.BindingContext[dsPubs1, "authors"].Count ); 
    } 
    

    自定義格式和數(shù)據類型轉換

    您可以使用 Binding 類的FormatParse 事件為綁定到控件的數(shù)據提供自定義格式。通過這些事件,您可以控制在用戶界面中顯示數(shù)據的方式以及從用戶界面中獲取數(shù)據和分析數(shù)據的方式,以便更新基礎數(shù)據。還可以使用這些事件來轉換數(shù)據類型,以便源數(shù)據類型和目標數(shù)據類型兼容。

    如果控件上綁定屬性的數(shù)據類型與數(shù)據源中數(shù)據的數(shù)據類型不匹配,則會引發(fā)異常。如果您需要綁定不兼容的類型,則應該使用 Binding 對象上的 FormatParse 事件。

    當從數(shù)據源中讀取數(shù)據并將其顯示在控件中時,以及當從控件中讀取數(shù)據并使用它來更新數(shù)據源時,將發(fā)生 Format 事件。當從數(shù)據源中讀取數(shù)據時,Binding 對象將使用 Format 事件在控件中顯示格式化數(shù)據。當從控件中讀取數(shù)據并使用它來更新數(shù)據源時,Binding 對象將使用 Parse 事件來分析數(shù)據。

    FormatParse 事件使您可以創(chuàng)建用于顯示數(shù)據的自定義格式。例如,如果表中的數(shù)據的類型是 Decimal,則您可以通過將 ConvertEventArgs 對象的 Value 屬性設置為 Format 事件中的格式化值,以本地貨幣格式顯示數(shù)據。因此,您必須在 Parse 事件中格式化顯示的值。

    下面的代碼示例將訂單金額綁定到文本框。FormatParse 事件用于在文本框期望的 string 類型和數(shù)據源期望的 decimal 類型之間進行轉換。

    private void BindControl() 
    { 
        Binding binding = new Binding( "Text", DataSet, 
    "customers.custToOrders.OrderAmount" ); 
        // Add the delegates to the event. 
        binding.Format += new ConvertEventHandler( DecimalToCurrencyString ); 
        binding.Parse  += new ConvertEventHandler( CurrencyStringToDecimal ); 
        text1.DataBindings.Add( binding ); 
    } 
    private void DecimalToCurrencyString( object sender, ConvertEventArgs cevent ) 
    { 
        // The method converts only to string type. Test this using the  
    DesiredType. 
        if( cevent.DesiredType != typeof( string ) ) return; 
        // Use the ToString method to format the value as currency ("c"). 
        cevent.Value = ((decimal)cevent.Value).ToString( "c" ); 
    } 
    private void CurrencyStringToDecimal( object sender, ConvertEventArgs cevent ) 
    { 
        // The method converts back to decimal type only.  
        if( cevent.DesiredType != typeof( decimal ) ) return; 
        // Converts the string back to decimal using the static Parse method. 
        cevent.Value = Decimal.Parse( cevent.Value.ToString(), 
                    NumberStyles.Currency, null ); 
    } 
    

    使用模型-視圖-控制器模式來實現(xiàn)數(shù)據驗證

    通過將數(shù)據結構綁定到用戶界面元素,用戶可以編輯數(shù)據并確保所做更改隨后被寫回到基礎數(shù)據結構。通常,您需要檢查用戶對數(shù)據所做的更改,以確保輸入的值有效。

    上一節(jié)中介紹的 FormatParse 事件提供了一種用于截獲用戶對數(shù)據所做更改的方法,以便可以檢查數(shù)據的有效性。但是,該方法要求與自定義格式代碼一起實現(xiàn)數(shù)據驗證邏輯(通常是在窗體級別)。如果在事件處理程序中同時實現(xiàn)這兩種職責,則會使您的代碼難以理解和維護。

    更為雅致的辦法是對代碼進行設計,以使其使用模型-視圖-控制器 (MVC) 模式。該模式提供了在通過數(shù)據綁定編輯和更改數(shù)據時涉及到的各種職責的自然分隔。您應該在負責以特定格式呈現(xiàn)數(shù)據的窗體內實現(xiàn)自定義格式,然后將驗證規(guī)則與數(shù)據本身相關聯(lián),以便在多個窗體中重新使用這些規(guī)則。

    在 MVC 模式中,數(shù)據本身被封裝在模型對象中。視圖對象是數(shù)據所綁定到的 Windows 窗體控件。對該模型所做的所有更改都由一個中間控制器對象處理,該對象負責提供對數(shù)據的訪問,并且負責控制通過視圖對象對數(shù)據所做的任何更改。控制器對象提供了一個用于驗證對數(shù)據所做更改的自然位置,所有用戶界面驗證邏輯都應該在這里實現(xiàn)。

    圖 2.5 描繪了 MVC 模式中的三個對象之間的結構關系。


    2.5 模型-視圖-控制器模式中的對象

    以這種方式使用控制器對象具有許多優(yōu)點。您可以配置一個普通的控制器以提供自定義驗證規(guī)則,這些規(guī)則可以在運行時根據某些上下文信息(例如,用戶的角色)進行配置。或者,您還可以提供許多個控制器對象,每個控制器對象都實現(xiàn)特定的驗證規(guī)則,然后在運行時選擇適當?shù)膶ο蟆o論采用哪種方法,因為所有驗證邏輯都被封裝在控制器對象中,所以視圖和模型對象都不需要更改。

    除了分隔數(shù)據、驗證邏輯和用戶界面控件以外,MVC 模型還為您提供了一種在基礎數(shù)據更改時自動更新用戶界面的簡單方法。控制器對象負責在發(fā)生通過其他某些編程手段對數(shù)據進行更改時通知用戶界面。Windows 窗體數(shù)據綁定偵聽由綁定到控件的對象生成的事件,以便用戶界面可以自動響應對基礎數(shù)據所做的更改。

    要實現(xiàn)用戶界面的自動更新,您應該確保控制器為每個可能更改的屬性實現(xiàn)一個更改通知事件。事件應該遵循命名約定<property>Changed,其中 <property> 是屬性的名稱。例如,如果控制器支持 Name 屬性,則它還應該支持 NameChanged 事件。如果名稱屬性的值更改,則應該激發(fā)該事件,以便 Windows 窗體數(shù)據綁定可以處理它并更新用戶界面。

    下面的代碼示例定義了一個 Customer 對象,該對象實現(xiàn)了 Name 屬性。CustomerController 對象處理 Customer 對象的驗證邏輯并支持 Name 屬性,而該屬性又表示基礎 Customer 對象上的 Name 屬性。每當該名稱更改時,此控制器都將激發(fā)一個事件。

    public class Customer 
    { 
        private string _name; 
        public Customer( string name ) { _name = name; } 
        public string Name 
        { 
            get { return _name; } 
            set { _name = value; } 
        } 
    } 
    public class CustomerController 
    { 
        private Customer _customer = null; 
        public event EventHandler NameChanged; 
        public Customer( Customer customer ) 
        { 
            this._customer = customer; 
        } 
        public string Name 
        { 
            get { return _customer.Name; } 
            set 
            { 
                 // TODO: Validate new name to make sure it is valid. 
                _customer.Name = value;  
                // Notify bound control of change. 
                if ( NameChanged != null ) 
                    NameChanged( this, EventArgs.Empty ); 
            } 
        } 
    } 
    

    Customer 數(shù)據源成員在聲明時需要進行初始化。在前面的示例中,需要將 customer.Name 成員初始化為空字符串。這是因為在數(shù)據綁定發(fā)生之前,.NET 框架沒有機會與該對象進行交互并設置默認的空字符串設置。如果未初始化 customer 數(shù)據源成員,則在嘗試從未初始化的變量中檢索值時,將導致運行時異常。

    在下面的代碼示例中,窗體具有一個 TextBox 對象 textbox1,它需要綁定到客戶的名稱。代碼將 TextBox 對象的 Text 屬性綁定到控制器的 Name 屬性。

    _customer = new Customer( "Kelly Blue" ); 
    _controller = new CustomerController( _customer ); 
    Binding binding = new Binding( "Text", _controller, "Name" ); 
    textBox1.DataBindings.Add( binding ); 
    

    如果更改了客戶的名稱(使用控制器上的 Name 屬性),則會激發(fā) NameChanged 事件,并且自動更新文本框以反映新的名稱值。

    在基礎數(shù)據更改時更新用戶界面

    您可以使用 Windows 窗體數(shù)據綁定在相應的基礎數(shù)據更改時自動更新用戶界面。通過在綁定的對象上實現(xiàn)一個更改通知事件,可以完成該任務。更改通知事件按照以下約定命名。

    public event EventHandler Changed; 
    

    因此,假設您將某個對象的 Name 屬性綁定到用戶界面,然后該對象的名稱由于其他某種處理而更改,則您可以通過實現(xiàn)綁定對象上的 NameChanged 事件來自動更新用戶界面,以反映新的 Name 值。

    返回頁首返回頁首

    小結

    在確定如何在智能客戶端處理數(shù)據時,涉及到許多不同的注意事項。您需要確定是否緩存以及如何緩存您的數(shù)據,并且確定如何處理數(shù)據并發(fā)問題。您將經常決定使用 ADO.NET 數(shù)據集來處理您的數(shù)據,并且您還可能將決定利用 Windows 窗體數(shù)據綁定功能。

    在許多情況下,只讀引用數(shù)據和瞬態(tài)數(shù)據需要進行不同的處理。因為智能客戶通常使用這兩種類型的數(shù)據,所以您需要確定在應用程序中處理各個類別數(shù)據的最佳方式。

    轉到原英文頁面


    posted on 2006-02-10 14:51 TrampEagle 閱讀(540) 評論(0)  編輯  收藏 所屬分類: 技術文摘
    主站蜘蛛池模板: 91亚洲精品麻豆| 久久亚洲精品成人av无码网站| 亚洲中文无码永久免费| 国产成人免费高清激情明星| 91亚洲va在线天线va天堂va国产| 日本在线看片免费| 久久久久亚洲精品天堂| 99热这里有免费国产精品| 亚洲第一永久在线观看| 免费国产成人高清在线观看网站 | 国产精品永久免费视频| 亚洲综合国产精品第一页| 99精品全国免费观看视频..| 亚洲av无码一区二区三区网站| 99久热只有精品视频免费看| 亚洲乱码日产精品BD在线观看| 少妇高潮太爽了在线观看免费| 亚洲人成综合网站7777香蕉| 国产美女做a免费视频软件| 一级特级女人18毛片免费视频| 亚洲精品乱码久久久久久| **毛片免费观看久久精品| 国产成人亚洲综合网站不卡| 免费在线观看的黄色网址| 最新国产乱人伦偷精品免费网站| 亚洲色av性色在线观无码| 国产国产人免费视频成69大陆 | **真实毛片免费观看| 亚洲欧美第一成人网站7777 | 日韩免费a级在线观看| eeuss草民免费| 亚洲白嫩在线观看| 无码不卡亚洲成?人片| 99久久国产免费-99久久国产免费| 亚洲精品一二三区| 91麻豆精品国产自产在线观看亚洲| 91av视频免费在线观看| 老司机午夜性生免费福利| 亚洲综合成人网在线观看| 国产视频精品免费| 91av免费观看|