共用方式為


第 4 章:儲存體

 

簡介
第 1 章:「Longhorn」 應用程式模型
第 2 章:建置 「Longhorn」 應用程式
第 3 章:控制項和 XAML

第 4 章:儲存體

Brent Rector
明智的 Owl 諮詢

2004 年 1 月

UPDATE:雖然此內容中可能說明的內容,但 「WinFS」 不是 Longhorn 作業系統隨附的功能。不過,「WinFS」將在 Windows 平臺上于未來日期提供,這就是為什麼本文會繼續提供您資訊的原因。

目錄

什麼是 WinFS?
WinFS 程式設計模型
使用 WinFS API 和 SQL
總結

在某些方面, 個人電腦 的名稱不足。 大部分的人不會使用個人電腦來計算。 他們使用電腦透過電子郵件或立即訊息) 通訊 (,以及儲存及組織其個人資料 (,例如電子郵件、檔、圖片和數位音樂) 。 不幸的是,雖然您的電腦目前很妥善地儲存此資料,但它會執行相當差的工作,讓您組織資訊,以便稍後找到。

過去十年來,磁片容量每年大約成長 70%。 目前可以購買超過 250 GB (GB) 儲存體的磁片磁碟機。 未來幾年可能會有 500 GB 的磁片磁碟機可供使用,而且許多系統會有一個以上的磁片磁碟機。 我剛在撰寫本章的電腦上快速檢查,而且我只有 200 GB 的磁碟空間在 114,129 資料夾中有 283,667 個檔案。 當我忘記確切放置檔案的位置時,可能需要一些時間才能再次找到它。 在最糟的情況下,我必須搜尋每個磁片的整個內容。 在數年內,人們將能夠儲存數百萬個檔案,其中大部分的檔案若沒有改善,他們永遠不會再看到一次。

人們很難在電腦上尋找資訊的原因之一,是因為使用者組織資料的能力有限。 目前資料夾和檔案的檔案系統支援原本很正常,因為大部分人很熟悉,而且檔案數目相對較小。 不過,它無法輕易地讓您儲存同事 Bob 在當地駐留的 2007 公司午餐上播放球的影像,稍後在搜尋檔時尋找影像:

  • 提及 Bob
  • 牽涉到運動
  • 與公司活動相關
  • 與駐留或其周圍區域有關
  • 已在 2007 年建立

當您想要以多種方式分類資料時,階層式資料夾結構無法正常運作。 因此,我們目前有一個問題,因為我們有許多要儲存的內容,而且沒有好方法可以分類它。 除了將一組固定關鍵字附加至資料,許多人員除了分類資訊之外,還需要關聯資料。 例如,我可能會想要將圖片與公司午餐產生關聯,或者我想要將圖片與 Bob 建立關聯,這也是我做為連絡人的組織成員。

另一個問題是,我們會以多個格式將相同專案儲存在多個位置。 開發人員花很多時間和精力建立自己的唯一儲存體抽象概念,以取得日常資訊,例如人員、地點、時間和事件。 例如,Microsoft Outlook 具有連絡人的定義。 Microsoft Windows 通訊錄也有自己的連絡人定義。 每個立即傳訊應用程式都有另一個。 每個應用程式都會將其連絡人的定義儲存在唯一、隔離的資訊接收器中。

資料儲存體目前的方法有一些問題,包括下列各項:

  • 開發人員會重複重新建立基本資料抽象概念。
  • 多個應用程式無法輕鬆地共用一般資料。
  • 相同的資訊位於多個位置。
  • 使用者重複輸入相同的資訊。
  • 個別的資料複本會變成未同步處理。
  • 沒有資料變更的通知。

什麼是 WinFS?

WinFS 是 Longhorn 中的新儲存系統。 它以三種方式改善 Microsoft Windows 平臺。 首先,它可讓您以多種方式將資訊分類,並將某個資訊專案與另一個專案產生關聯。 其次,它會為每天收集的資訊提供常見的儲存格式,例如處理人員、地點、影像等資訊。 第三,它會提升多個廠商多個應用程式之間通用資訊的資料共用。

WinFS 是儲存體平臺

WinFS 是一個作用中儲存平臺,可用來組織、搜尋及共用所有類型的資訊。 此平臺會定義豐富的資料模型,可讓您使用和定義儲存體平臺可以使用的豐富資料類型。 WinFS 包含許多描述實際實體的架構,例如影像、檔、人員、位置、事件、工作和訊息。 這些實體可能相當複雜。 例如,人員可以有多個名稱、多個實體和電子郵件地址、目前的位置等等。

獨立軟體廠商 (ISV) 也可以定義自己的新資料類型,並將其架構提供給 WinFS。 藉由允許 WinFS 管理複雜的儲存問題,ISV 可以專注于開發其唯一的應用程式邏輯,並利用 WinFS 更豐富的儲存設備來取得其日常和自訂資料。

WinFS 包含關聯式引擎,可讓您使用功能強大的關聯式查詢來尋找儲存體類型的實例。 WinFS 可讓您使用關聯性,以有意義的方式結合這些儲存體實體。 一個連絡人可以是組織員工群組的成員,同時是特定位址的家庭群組成員。 ISV 會自動獲得搜尋、複寫、保護及建立其唯一資料類型和預先定義 Windows 資料類型之間的關聯性的能力。

此結構可讓使用者對系統提出問題,並要求它尋找資訊,而不是要求系統個別搜尋資料夾。 例如,您可以要求 WinFS 從您沒有電話號碼的立即 Messenger 布建清單上尋找所有電子郵件訊息。 使用關聯式查詢,您可以在當月為具有生日的特定員工找到家庭的所有成員。

WinFS 也支援多個彈性的程式設計模型,可讓您為工作選擇適當的應用程式程式設計介面 (API) 。 您可以使用結構化查詢語言來存取存放區, (SQL) 。 或者,您可以使用 .NET 類別和物件來存取資料存放區。 您也可以在資料存放區上使用 XML 型 API。 WinFS 也支援透過傳統 Microsoft Win32 檔案系統 API 進行資料存取。 您甚至可以混合並比對,也就是說,對單一工作使用多個 API。 不過,針對大部分用途,開發人員會使用 Managed 類別 API 來變更 WinFS 存放區中的資料。 相較于使用物件 API,使用原始 SQL 語句進行更新通常更為複雜。

此外,WinFS 還提供一組資料服務,用於監視、管理和操作您的資料。 您可以在特定資料項目變更時註冊以接收事件。 您可以排程 WinFS 將資料複寫至其他系統。

WinFS 是檔案系統

對於傳統檔案型資料,例如文字檔、音訊播放軌和視訊剪輯,WinFS 是新的 Windows 檔案系統。 一般而言,您會將檔案的主要資料、檔案資料流程儲存為 NTFS 磁片區上的檔案。 不過,每當呼叫變更或新增具有 NTFS 檔案資料流程元件之專案的 API 時,WinFS 會從資料流程擷取中繼資料,並將中繼資料新增至 WinFS 存放區。 此中繼資料描述資料流程的相關資訊,例如其路徑,以及 WinFS 可以從資料流程擷取的任何資訊。 視檔案內容而定,此中繼資料可以是檔) 的作者 (、音訊檔案的類型 () 、PDF 檔案) (關鍵字等等。 WinFS 會同步處理 NTFS 駐留的檔案資料流程和 WinFS 駐留中繼資料。 新的 Longhorn 應用程式也可以選擇將其檔案串流直接儲存在 WinFS 中。 您可以使用現有的 Win32 檔案系統 API 或新的 WinFS API 來存取檔案資料流程。

WinFS 不只是檔案系統

檔案系統會管理檔案和資料夾。 雖然 WinFS 會管理檔案和資料夾,但它也會管理所有類型的非檔案型資料,例如個人連絡人、事件行事曆、工作和電子郵件訊息。 WinFS 資料可以是結構化、半結構化或非結構化。 結構化資料包含架構,其會額外定義資料的用途,以及您應該如何使用它。 因為 WinFS 是關聯式系統,所以它會針對語意、交易和條件約束強制執行資料完整性。

WinFS 不只是關聯式系統。 它同時支援階層式儲存體和關聯式儲存體。 它支援以結構化型別和物件的形式傳回資料,也就是型別加上行為。 您可能會將 WinFS 視為階層式、關聯式、物件導向的資料儲存系統,雖然它實際上包含每個傳統儲存系統的特定層面。 WinFS 超越傳統檔案系統和關係資料庫系統。 這是最新 Windows 平臺上所有類型的資料存放區。

WinFS 和 NTFS

您可以將檔案儲存在傳統 NTFS 檔案系統或新的 WinFS 資料存放區中,就像您可以儲存在 FAT32 或目前CD-ROMs或 NTFS 中一樣。 一般而言,儲存在 NTFS 中的檔案不會顯示在 WinFS 中。 使用新 WinFS API 的 Longhorn 應用程式可以存取儲存在 WinFS 或 NTFS 中的資料。 此外,Longhorn 應用程式可以繼續使用 WIN32 API 來存取儲存在 NTFS 檔案系統中的資料。

檔案升級

檔案位於 WinFS 中。 任何具有檔案資料流程元件的專案都可以參與升級/降級,我們通常會呼叫 元資料處理。 當 WinFS 升級檔案時,它會從已知的 NTFS 檔案內容擷取中繼資料,並將中繼資料新增至 WinFS 資料存放區。 檔案的實際資料流程會保留在 NTFS 檔案系統中。 然後,您可以查詢有關中繼資料的 WinFS,就像檔案原生位於 WinFS 內一樣。 WinFS 也會偵測 NTFS 檔案中的變更,並視需要更新 WinFS 資料存放區內的中繼資料。

檔案匯入和匯出

您也可以從 NTFS 將檔案匯入 WinFS,並將檔案從 WinFS 匯出至 NTFS。 匯入和匯出檔案會移動檔案內容和中繼資料。 匯入或匯出之後,新檔案與原始檔案完全無關。

WinFS 程式設計模型

WinFS 程式設計模型包括資料存取、資料操作、WinFS 資料類別擴充性、資料同步處理、資料變更通知,以及事件優先順序。 資料存取和資料操作可讓您建立、擷取、更新和刪除儲存在 WinFS 中的資料,以及練習網域特定行為。 資料類別擴充性可讓您使用自訂欄位和自訂類型來擴充 WinFS 架構。 資料同步處理可讓您同步處理 WinFS 存放區與 WinFS 與非 WinFS 存放區之間的資料。

WinFS 資料模型階層的頂端是 WinFS 服務,只是 WinFS 的實例。 服務階層中的一個層級是 磁片區。 磁片區是專案的最大自發容器。 每個 WinFS 實例都包含一或多個磁片區。 在磁片區內是 專案

WinFS 引進專案作為一致性和作業的新單位,而不是檔案。 儲存系統會儲存專案。 您具有豐富的查詢功能。 專案實際上是儲存系統的基底類型。 因此,專案具有一組資料屬性,並提供基本的查詢功能。

人員通常會根據一些在指定網域中有意義的系統,在真實世界中組織資料。 所有這些系統都會將資料分割成具名群組。 WinFS 會使用 資料夾的概念來建立這個概念的模型。 資料夾是特殊類型的專案。 有兩種類型的資料夾: 內含專案資料夾虛擬資料夾

內含專案資料夾是一個專案,其中包含保存其他專案的連結,以及建立檔系統資料夾通用概念的模型。 只要至少有一個保存連結參考專案,專案就會存在。 請注意,內含專案資料夾不會直接包含資料夾中邏輯上存在的專案,而是包含這些專案的連結。 這可讓多個內含專案資料夾 包含 相同的專案。

虛擬資料夾是專案的動態集合。 它是一組具名的專案。 您可以明確列舉集合,或指定傳回集合成員的查詢。 查詢指定的虛擬資料夾相當有趣。 當您將新專案新增至符合虛擬資料夾查詢準則的存放區時,新專案會自動成為虛擬資料夾的成員。 虛擬資料夾本身是專案。 在概念上,它代表專案的一組非保留連結,如圖 4-1 所示。

圖 4-1: WinFS 資料模型階層

有時候,您需要建立內含專案高度限制的概念模型,例如,內嵌在電子郵件訊息中的 Microsoft Word檔是,也就是說,系結至其容器更緊密,例如,包含在資料夾中的檔案。 WinFS 使用 內嵌專案來表示此概念。 內嵌專案是專案內的特殊連結類型, (名為 Embedded Link) 參考另一個專案。 參考的專案可以系結至 ,或只能在包含專案的內容中操作。

最後,WinFS 提供 類別 的概念來分類專案。 您可以將一或多個類別與 WinFS 中的每個專案建立關聯。 WinFS 實際上會將類別名稱標記至專案。 然後,您可以在搜尋中指定類別名稱。 WinFS 資料模型允許類別階層的定義,因此啟用類似樹狀的資料分類。

組織資訊

所有這些功能都允許五種方式在 WinFS 中組織您的資訊:

  • 階層式資料夾型組織。 使用這種方法,您仍然具有傳統的階層式資料夾和專案組織結構。 WinFS 資料存放區中的所有專案都必須位於容器中,而且其中一個容器類型是資料夾。
  • 類型型組織。 專案一律為特定類型。 例如,您有 Person 專案、相片專案、組織專案,以及其他許多可用的類型。 您甚至可以建立新的類型,並將其儲存在 WinFS 資料存放區中。
  • 專案屬性型組織。 您可以檢視已將一或多個屬性設定為指定值的專案。 實際上,這是虛擬資料夾檢視,其查詢會傳回具有指定屬性指定值的專案。
  • 以關聯性為基礎的組織。 您可以根據專案與其他專案的關聯性來擷取專案,例如,人員可以是組織的成員,也可以根據此關聯性來組織或搜尋專案。
  • 以類別為基礎的組織。 您可以建立和關聯任意數目的使用者定義關鍵字與專案。 接著,您可以擷取具有相關聯關鍵字特定值的專案。 不過,您無法建立分類分類法,因此此組織技術不像上述方法一樣強大。

WinFS API

WinFS 提供三個數據存取 API:受控 WinFS API、ADO.NET API 和 WIN32 API。 WinFS API 是強型別的「高階」API。 ADO.NET 提供較低層級的 API,以 XML 或資料表或資料列的形式來處理資料。 使用 ADO.NET,您可以使用 Transact-Structured查詢語言 (T-SQL) ,並使用 T-SQL 的 FOR XML 功能擷取 XML 中的資料,來存取儲存在 WinFS 中的資料。 WIN32 API 允許存取儲存在 WinFS 中的檔案和資料夾。

您可能偏好使用多個存取模式來解決問題。 例如,您可以發出 T-SQL 查詢,以傳回一組連絡人做為 WinFS 連絡人類型的 Managed 物件。 不論您使用的 API 為何,每個 API 最終都會使用 T-SQL 操作 WinFS 存放區中的資料。

在許多情況下,您會偏好使用受控 WinFS API。 這些.NET Framework類別會自動執行在物件導向程式設計建構之間轉譯所需的物件關聯性對應,並執行必要的 T-SQL 來達成 WinFS 資料存取。

使用 Managed WinFS 類別

WinFS Managed 類別位於 System.Storage 命名空間及其巢狀命名空間中。 許多應用程式也會使用命名空間中的 System.Storage.Core WinFS 類型定義。 您也可以使用來自更特製化命名空間的類型。 例如,管理連絡人系統定義的 Managed 類別位於命名空間中 System.Storage.Contact 。 為了簡單起見,本章中的所有程式碼範例都會使用下列一組 using 宣告:

using System.Storage;
using System.Storage.Core;
using System.Storage.Contact;

ItemCoNtext

WinFS 存放區是由組織成資料夾並分類的專案所組成。 使用 WinFS 的第一個步驟是識別您想要使用的專案集。 我們呼叫這個進程 系結,而且專案集可以是下列任一項:

  • 整個磁片區 (也稱為 根資料夾)
  • 指定磁片區中專案的可識別子集,例如特定內含專案資料夾或虛擬資料夾
  • 個別專案
  • WinFS 共用 (,可識別磁片區、資料夾、虛擬資料夾或個別專案)

若要系結至一組專案,您可以建立 System.Storage.ItemContext 物件,並將其連線至 WinFS 資料存放區。 使用靜態 System.Storage.ItemContext.Open 協助程式方法來建立 ItemContext 物件。

下列程式碼會 ItemContext 建立連線至預設本機 WinFS 磁片區的 。 預設值為 \\local-computer-name\DefaultStore 共用:

System.Storage.ItemContext ctx = System.Storage.ItemContext.Open ();
§
ctx.Close();

或者,您可以將字串傳遞至建構函式,以將專案內容連線至特定的 WinFS 存放區。 下列程式碼會建立連線至 \\machine\Legal Documents 共用所識別之 WinFS 共用的專案內容:

ItemContext ctx = null;
try {
ctx = ItemContext.Open (@"\machine\Legal Documents");
  §
}
finally {
  if (ctx != null) ctx.Dispose();
}

請務必在您完成使用內容物件時立即關閉或處置,而不論例外狀況為何。 使用 ItemContext 重要的非受控資源,例如與存放區的連線,您應該及時釋放。 為了盡可能方便關閉內容,類別 ItemContext 會實作 IDisposable 介面。 因此,您可以使用 C# using 語句,如下列範例所示來釋放這些資源:

using (ItemContext ctx = ItemContext.Open (@"D:\MyStore")) {
§
}

將新專案儲存在 WinFS 資料存放區中

WinFS 資料存放區中的每個專案都必須是存放區資料夾的成員。 您可以呼叫非常具名的靜態方法 ,以取得資料夾階層的根目錄 System.Storage.Folder.GetRootFolder 。 不過,還有數個系統定義的容器可用來儲存應用程式特定資料。 您通常會使用 類別上的 UserDataFolder 其中一個靜態方法來擷取資料夾,然後放置新專案。

取得資料夾

在下列範例中,如果目前使用者的個人連絡人資料夾存在,則會在不存在時加以建立。 請注意,這是一個有點常見的範例:如果使用者第一次登入系統時,系統會自動建立使用者的個人連絡人資料夾,但有機會在不存在時顯示如何建立預期的資料夾。

ItemContext ctx = ItemContext.Open ();
WellKnownFolder contactsFolder =
          UserDataFolder.FindUsersWellKnownFolderWithType (ctx,
                         GeneralCategories.PersonalContactsFolder);

if (contactsFolder == null) {
    //create the Personal Contacts folder
    Folder userDataFolder = UserDataFolder.FindMyUserDataFolder (ctx);
    WellKnownFolder subFolder = new WellKnownFolder (ctx);
    CategoryRef category = new CategoryRef (ctx,
                            GeneralCategories.PersonalContactsFolder);

    // Associate the PersonalContactsFolder category to the folder
    subFolder.FolderType = category;
    userDataFolder.AddMember (subFolder);
    ctx.Update();
}

上述程式碼會執行一些有趣的事。 首先,我嘗試找出包含在使用者個人資料資料夾階層中的現有資料夾。 我不是依已知名稱尋找資料夾。 相反地,我正在尋找使用者個人資料樹狀結構內的資料夾,該資料夾先前已與已知的類別 PersonalContactsFolder 相關聯。 當您選取 [我的連絡人] 時,殼層會顯示此資料夾。

此資料夾通常已經存在,但若不存在,我就會擷取使用者資料階層的根資料夾。 我建立類型為 的新專案, WellKnownFolder 然後建立已知類別的參考,也就是 PersonalContactsFolder 類別。 然後,我將新資料夾的類型設定為 PersonalContactsFolder 類別類型,最後,我會將新資料夾新增至其包含的資料夾,也就是使用者的個人資料根資料夾。 WinFS 不會儲存資料存放區的任何變更,直到您 Update 呼叫專案內容 (,我經常忘記執行) 。

當然,這是尋找個人連絡人資料夾的詳細資訊方式。 我想要示範如何運作。 一般而言,我改用下列程式碼。 方法 FindMyPersonalContactsFolder 會尋找現有的資料夾。

WellKnownFolder userDataFolder =
         UserDataFolder.FindMyPersonalContactsFolder (ctx);

建立新專案

因為我現在有個人連絡人資料夾,所以在資料夾中建立新的連絡人似乎很適合。 在下列範例中,我將建立一些人員連絡人,並將其新增至資料夾:

Person[] CreateFriends (ItemContext ctx) {
  string[] GivenNames = { "Monica", "Rachel", "Chandler",
                          "Joey",   "Phoebe", "Ross"};
  string[] SurNames = { "Uchra",    "Emerald",  "Ranier",
                         "Fibonacci", "Smorgasbord", "Uchra"};
  Person[] Friends = new Person [GivenNames.Length];
  
  for (int index = 0; index < GivenNames.Length; index++) {
    string linkName = GivenNames[index] + " " + SurNames[index];
    Person p = Person.CreatePersonalContact (ctx, linkName);
    Friends[index] = p;

    p.DisplayName = linkName;
    FullName fn = p.GetPrimaryName ();
    fn.GivenName = GivenNames[index];
    fn.Surname = SurNames[index];
  }
  ctx.Update ();
}

先前的程式碼會使用靜態 Person.CreatePersonalContact 方法。 這個方法

  • 在指定的專案內容中建立新的 Person 專案
  • 使用參考 Person 的指定名稱建立新的 FolderMember 關聯性
  • FolderMember 關聯性加入至 PersonalContactsFolderRelationship 集合

我接著會更新 DisplayName Person 專案的 、 GivenNameSurname 屬性。 一如往常,我在專案內容上呼叫 Update ,以將變更儲存至資料存放區。

讓我們更仔細地查看 CreatePersonalContact 方法。 此命令相當於:

// Find the PersonalContacts folder
WellKnownFolder contactsFolder =
           UserDataFolder.FindUsersWellKnownFolderWithType (ctx,
                             GeneralCategories.PersonalContactsFolder);
// Create a new Person item
Person p = new Person (ctx);

// Need a folder relationship that references the new Person
FolderMember fm = new FolderMember (p, linkName);
folder.Relationships.Add (fm);
ctx.Update ();

關聯性專案

WinFS 會定義關聯性資料模型,可讓您將專案彼此關聯。 當您定義資料類型的架構時,您可以將零個或多個關聯性定義為架構的一部分。 例如,資料夾架構會定義 FolderMember 關聯性。 組織架構會定義關聯 Employee 性。 針對每個這類定義的關聯性,有一個類別代表關聯性本身。 這個類別衍生自 類別, Relationship 並包含關聯性類型特定的成員。 也有強型別的「虛擬」集合類別。 這個類別衍生自 VirtualRelationshipCollection ,並允許建立和刪除關聯性實例。

關聯性會將來源專案與目標專案產生關聯。 在上一個範例中,[個人連絡人] 資料夾是來源專案,而 Person 專案是目標專案。 關聯 FolderMember 性基本上表示 Person 專案與個人連絡人資料夾有關,做為資料夾的成員。

當您定義關聯性時,您可以定義關聯性是否讓目標專案保持存在— 保留關聯性,或不會讓目標專案存在— 參考關聯性。 當您建立目標專案的保留關聯性時,WinFS 會遞增目標專案的參考計數。 當 WinFS 刪除保留關聯性時,它會遞減目標專案的參考計數。 當專案參考計數達到零時,存放區中不再存在。 當您建立或終結目標的參考關聯性時,WinFS 永遠不會改變目標的參考計數。 因此,當目標專案參考計數達到零時,目標專案可能會從存放區消失,而關聯性可能會參考不再存在的專案。

WinFS 會將關聯 FolderMember 性定義為保存關聯性。 大部分的其他關聯性類別都是參考關聯性。

資料夾專案

現在您已瞭解連結專案,我可以精簡資料夾專案的描述。 Folder 是具有連結專案集合的 WinFS 專案。 集合中每個 Link 專案的目標都是資料夾的成員。 屬性 Folder.Members 代表這個連結集合。

請注意,這可提供比傳統檔系統資料夾更大的 WinFS 資料夾彈性。 資料夾的成員可以是檔案和非檔案專案。 特定專案有多個連結可以同時位於許多資料夾中。 換句話說,多個資料夾可以 包含 相同的專案。

其他專案類型

一般而言,您會在 WinFS 存放區中建立其他專案類型,如先前範例所示。 每個類型偶爾都會有自己的特殊使用模式。 例如,我們可以讓組織成為 [個人連絡人] 資料夾的成員,因此讓我們建立一個:

Organization cp = FindOrCreateOrganization (ctx, "Main Benefit");
§
Organization FindOrCreateOrganization (ItemContext ctx, string orgName) {
  Organization o =
    Organization.FindOne (ctx, "DisplayName='" + orgName + "'");
  if (o == null) {
    Folder Pcf = UserDataFolder.FindMyPersonalContactsFolder (ctx);

    o = new Organization (ctx);
    o.DisplayName = orgName;

    Folder pcf = UserDataFolder.FindMyPersonalContactsFolder (ctx);

    pcf.AddMember (o, o.DisplayName.ToString ());
    ctx.Update ();
  }
  return o;
}

現在讓我們將員工新增至該組織:

enum Names { Monica, Rachel, Chandler, Joey, Phoebe, Ross }
§
Person[] Friends = CreateFriends (ctx);
Organization cp = FindOrCreateOrganization (ctx, "Main Benefit");
AddEmployeeToOrganization (ctx, Friends [(int)Names.Rachel],
  cp);
§
void AddEmployeeToOrganization (ItemContext ctx, Person p, Organization o) {
  EmployeeData ed = new EmployeeData (ctx);

  ed.Name = p.DisplayName;
  ed.Target_Key = p.ItemID_Key;
  o.Employees.Add (ed);
  ctx.Update ();
}

同樣地,我們可以在個人連絡人資料夾中建立家庭。 請注意,家庭不代表家庭。 家庭可能是一組室成員。 WinFS 具有系列的其他架構,但我會將該架構保留為讀者的練習。

CreateHousehold (ctx, Friends [(int) Names.Chandler],
                      Friends [(int) Names.Joey]);
CreateHousehold (ctx, Friends [(int) Names.Monica],
                      Friends [(int) Names.Rachel]);
§
void CreateHousehold (ItemContext ctx, Person p1, Person p2) {
  Household h = new Household (ctx);
  h.DisplayName = p1.GetPrimaryName().GivenName + " and " +
                  p2.GetPrimaryName().GivenName + " household";

  Folder pcf = UserDataFolder.FindMyPersonalContactsFolder (ctx);
  pcf.AddMember (h, h.DisplayName.ToString ());

  // Add first person to the household
  HouseholdMemberData hhmd = new HouseholdMemberData (ctx);
  hhmd.Name = p1.DisplayName;
  hhmd.Target_Key = p1.ItemID_Key;
  h.HouseholdMembers.Add (hhmd);

  // Add second person to the household
  hhmd = new HouseholdMemberData (ctx);
  hhmd.Name = p2.DisplayName;
  hhmd.Target_Key = p2.ItemID_Key;
  h.HouseholdMembers.Add (hhmd);
}

先前的範例使用我尚未討論過的概念。 請注意這一行程式碼中的 屬性用法 ItemID_Key

  hhmd.Target_Key = p1.ItemID_Key;

基本上, ItemID_Key 此值是參考 WinFS 存放區中專案的另一種方式,因此讓我們看看在存放區中尋找專案的方式。

如何尋找專案

當然,如果您之後無法輕易找到專案,則將專案放在資料存放區並不好。 類別 ItemContext 包含可用來擷取 WinFS 資料存放區中專案的實例方法。 您可以指定要尋找的專案類型,以及傳回專案必須符合的任何特殊條件約束。 此外,每個專案類別,例如、 PersonFileFolder 等等,也包含靜態方法,可讓您尋找該特定類型的專案。

方法 FindAll 會傳回一或多個符合指定準則的專案。 ItemContext.FindAll實例方法會要求您指定要尋找的專案類型。 此外,您可以選擇性地指定搜尋準則來縮小搜尋範圍。 例如,下列程式碼會尋找具有 DisplayName 其值開頭為 「Brent」 之屬性的所有 Person 專案。

FindResult res = ctx.FindAll (typeof(Person), "DisplayName='Brent%'");
foreach (Person p in res) {
    // Use the Person item somehow
}

或者,我可以使用 類別的 Person 靜態 FindAll 方法,如下所示:

FindResult res = Person.FindAll (ctx, "DisplayName='Brent%'");
foreach (Person p in res) {
    // Use the Person item somehow
}

在這兩個範例中 FindAll ,方法一律會傳回符合類型和指定準則的專案集合。 此集合可能不包含任何專案,但您不會收到 的 FindResult Null 參考。 因此,請一律逐一查看集合,以取得找到的專案。

當您知道只有單一專案符合所要求的類型和指定的篩選準則時,您可以使用 FindOne 方法。 不過,請注意, FindOne 方法會在找到一個符合您要求的多個專案時擲回例外狀況。

Person p = Person.FindOne (ctx, "DisplayName='Brent Rector'");

第二個字串參數是篩選運算式,可讓您指定傳回專案必須滿足的其他條件約束。 篩選運算式的基本格式是格式為 「 <propertyName> <operator> <propertyValue> 」 的字串。

WinFS 會呼叫運算式。 OPath 語法與用來識別 XML 檔中專案的運算式語法類似,但並不相同 XPath 。 此程式碼片段會傳回具有 「doc」 或 「txt」 副檔名之檔案的所有檔案專案:

FindResult Files = File.FindAll (ctx, "Extension='doc' || Extension='txt'");

這些運算式可能相當複雜。 例如,下列語句會傳回代表「主要權益」之雇主 DisplayName 員工的所有 Person 專案:

string pattern = "Source(EmployeeOf).DisplayName='Main Benefit'";
FindResult result = Person.FindAll (ctx, pattern);

以下是另一個。 我想要 Surname 不是 「Ranier」 的 Person 專案,而電子郵件地址不會以 「.edu」 結尾。

string filter = "PersonalNames[Surname!='Ranier'] &&
                 !(PersonalEmailAddresses[Address like '%.edu'])");
FindResult result = Person.FindAll (ctx, filter);

識別特定專案

您經常需要建立 WinFS 存放區中專案的參考。 最後,您會使用這些參考來找出適當的專案。 稍早在本章中,我示範如何使用連結來參考專案。 連結會針對參考使用易記字串型身分識別,而且此字串名稱在連結的包含資料夾中必須是唯一的。 換句話說,您需要資料夾及其其中一個包含的連結來識別參考的專案。

不過,只要您將連結新增至不同的資料夾,即可使用相同的易記字串名稱建立多個連結,讓單一資料夾內的所有名稱保持唯一。 請注意,具有相同易記文字名稱的這些多個連結實際上不需要參考相同的目標專案。 他們可以,但不需要。

在這種情況下,使用 搜尋具有特定易記文字名稱的所有連結 (FindAll ,例如,) 會傳回多個結果。 接著,您必須檢查每個連結的來源,以判斷包含的資料夾,然後判斷哪個連結會參考所需的專案。

我們需要一種方式來參考存放區中的任何任意專案,例如,假設我想要存放區中的第 3,287 個專案。 幸運的是,您可以確實這麼做。

ItemID_Key 值尋找專案

WinFS 會為每個新建立的專案指派 GUID 型識別碼,稱為其 ItemID_Key 屬性。 在實務上,值很可能在所有 WinFS 磁片區中都是唯一 ItemID_Key 的;不過,WinFS 仍會將此識別碼視為只在磁片區中是唯一的。 您可以使用此磁片區唯一值來識別 WinFS 磁片區中的任何專案。

Item GetItem (ItemContext ctx, SqlBinary itemID_Key) {
   // Convert itemID_Key to a string for use in the OPath filter 
   string hexItemID_Key = BitConverter.ToString (itemID_Key.Value);
   hexItemID_Key = "'0x" + hexItemID_Key.Replace ("-", String.Empty) + "'";

   // Build an opath filter expression.
   string query = "ItemID_Key=" + hexItemID_Key;

   return Item.FindOne (ctx, query);
}

常用功能

WinFS API 提供整個資料類別的數個功能。 這些功能為

  • 非同步
  • 交易
  • 通知
  • Blob/資料流程支援
  • 資料指標和分頁

非同步

WinFS API 可讓您以非同步方式執行查詢。 WinFS API 使用 .NET 標準非同步程式設計模型模式。

交易

WinFS 存放區是交易式存放區。 因此,WinFS 可讓您使用 BeginTransaction 物件上的 ItemContextCommitTransactionAbortTransaction 方法,對存放區進行交易式更新,如下列範例所示:

using (ItemContext ctx = ItemContext.Open()) {
  using (Transaction t = ctx.BeingTransaction()) {
    Person p = Person.FindOne (ctx,
        "PersonalNames[GivenName='Chandler' And SurName='Bing']" );
    Household h = Household.FindOne (ctx,
        "DisplayName = 'Chandler and Joey Household'");
    p.PersonalEAddresses.Add (new TelephoneNumber ("202", "555-1234"));
    p.Save ();
    h.Members.Add (p);
    h.Save ();
    t.Commit ();
  }
}

通知

WinFS 通知服務會使用短期和長期訂用帳戶的概念。 短期訂閱會持續到應用程式取消訂閱或應用程式結束為止。 長期訂用帳戶可讓應用程式重新開機。 WinFS API 監看員 是一組類別,可讓應用程式選擇性地通知 WinFS 存放區中的變更,並提供應用程式可保存的狀態資訊,以支援暫停/繼續案例。

類別 Watcher 可以通知您的應用程式 WinFS 物件不同層面的變更,包括下列各項:

  • 專案變更
  • 內嵌專案變更
  • 專案延伸模組變更
  • 關聯性變更

當監看員引發事件時,它會使用事件通知傳送監看員狀態資料。 您的應用程式可以儲存此狀態資料以供稍後擷取。 接著,您可以使用這個監看員狀態資料,向 WinFS 指出您想要接收在產生狀態之後發生之所有變更的事件。

監看員程式設計模型也允許停用加入、修改和移除事件的任何組合。 也可以設定為引發初始事件,以模擬新增所有現有專案、專案延伸模組、關聯性等等。

WinFS 監看員設計會細分為下表所述的類別。

類別 目的/描述
WatcherOptions 指定初始範圍和細微性選項的類別 StoreWatcher
StoreWatcher 用來監看 WinFS 專案、內嵌專案、專案延伸模組和關聯性的 quintessential 類別
WatcherState 可用來初始化 的不透明物件 StoreWatcher
ChangedEventHandler 類別,定義要呼叫的事件處理常式 StoreWatcher
ChangedEventArgs 傳遞為引數至 的類別 ChangedEventHandler
ItemChangeDetail 提供專案事件細微變更詳細資料的基類
ItemExtensionChangeDetail 衍生自 ItemChangeDetail 的類別,可提供專案擴充事件特有的其他變更詳細資料
RelationshipChangeDetail 衍生自 ItemChangeDetail 的類別,提供關聯性事件特有的其他變更詳細資料

您可以使用 StoreWatcher 類別為 WinFS 存放區中的某些專案建立監看員。 實例 StoreWatcher 會在指定的專案變更時引發事件。 您可以指定要watch的專案和階層類型。 根據預設,監看員

  • 不會引發初始事件以建立目前狀態
  • 監看專案和階層 (包括任何變更的立即子系)
  • 引發此專案或任何整個階層中子項上的新增、移除和修改事件
  • 針對此專案或整個階層中的任何子專案,引發專案延伸模組的新增、移除和修改事件
  • 針對此專案或任何整個階層中的子系是關聯性的來源,引發新增、移除和修改事件

因為監看員預設會監看指定專案及其子代中的變更,所以您可能會想要指定 WatchItemOnly 為監看員選項。 下列範例只會監看對所找到 Person 專案的變更:

Person p = Person.FindOne (ctx,
            "PersonalNames[GivenName='Rachel' and Surname='Emerald'");
StoreWatcher w = new StoreWatcher ( p, WatcherOptions.WatchItemOnly );

資料夾只是另一個 WinFS 專案。 您watch資料夾變更的方式與人員相同:

Folder f = · · ·
StoreWatcher w = new StoreWatcher (f, <WatcherOptions>);

您也可以watch專案指定關聯性的變更:

Person p = · · ·
StoreWatcher w = new StoreWatcher (p, typeof(HouseholdMember),
                                   <WatcherOptions> );
w.ItemChanged += new ChangedEventHandler (ItemChangedHandler);
w.Enabled = true;

// Change notifications now arrive until we unsubscribe from the event
  §
// Now we unsubscribe from the event
w.ItemChanged -= new ChangedEventHandler (ItemChangedHandler);
w.Dispose ();
§

// The change notification handler
void ItemChangedHandler (object source, ChangedEventArgs args) {
  foreach (ItemChangeDetail detail in args.Details) {
    switch (typeof(detail)) {
      case ItemExtensionChangeDetail:
        // handle added + modified + removed events for Item Extension
        break;

      case RelationshipChangeDetail:
        // handle added + modified + removed events for Relationship
        break;

      default:
      case ItemChangeDetail:
        // handle added + modified + removed events for Item or Embedded Item
        HandleItemChangeDetail (detail);
        break;
    }
  }
|

void HandleItemChangeDetail (ItemChangeDetail detail) {
  switch (detail.ChangeType) {
    case Added:          // handle added event
      break;

    case Modified:       // handle modified event
      break;

    case Removed:        // handle modified event
                break;
  }
}

Blob 和資料流程支援

Blob 和資料流程支援 API 在撰寫本文時仍會處於變動狀態。 如需如何在 WinFS 存放區中存取 Blob 和資料流程的最新資訊,請參閱檔。

資料指標和分頁

WinFS 類別中的各種 Find 方法可以傳回 (可能) 大型物件集合。 這個集合相當於資料庫世界中的資料列集。 傳統資料庫應用程式會使用 分頁資料指標 在大型資料列集內有效率地巡覽。 此資料指標會參考單一資料列 (精簡資料 指標) 或一組 (頁面資料指標) 的資料列。 概念是應用程式一次擷取一頁的資料列;它們也可以找出頁面內一個資料列,以進行定位的更新和刪除。 WinFS API 為開發人員提供類似的抽象概念,以處理大型集合。

根據預設,尋找作業會在傳回的集合上提供唯讀、可捲動的動態資料指標。 應用程式可以有引發的指標,以達到最大效能。 火水指標是順向資料指標。 應用程式可以一次擷取一頁的資料列,但下一個擷取作業會從後續的資料列集開始,而無法返回並重新擷取資料列。 也就是說,資料列會從存放區流向應用程式,例如來自火道的水,因此是名稱。

類別 CursorType 中的 FindParameters 屬性可讓應用程式在引發水壓和可捲動的資料指標之間進行選擇。 針對引發快取和可捲動的資料指標,應用程式可以使用 類別的 FindParameters 屬性來設定頁面大小 PageSize 。 根據預設,頁面大小會設定為 1。

資料綁定

您可以使用 WinFS 資料類別作為資料系結環境中的資料來源。 WinFS 類別會 IDataEntity 針對單一物件實作 () ,並為 IDataCollection 集合) 介面實作 (。 介面 IDataEntity 會提供通知給資料來源物件中屬性變更的資料系結目標。 介面 IDataCollection 允許判斷多型集合中物件的基底類型。 它也可讓您擷取 System.Windows.Data.CollectionManager ,它會巡覽集合的資料實體,並提供檢視 (,例如排序次序或篩選) 集合。 我在第 5 章中詳細討論資料系結。

安全性

WinFS 安全性模型基本上會以下列方式將 一 Rights 組 授與 Principal 上的 Item

  • 安全性是在 的 Items 層級設定。
  • 一組許可權可以授與至 上 Item 的安全性準則。 此集合包括:所有專案) 、CREATE_CHILD、ADMINISTER 和 AUDIT 的 READ、WRITE、DELETE、EXECUTE (。 (其他許可權可在 Folder items 上授與。)
  • 使用者和應用程式是安全性原則。 應用程式許可權會取代使用者權限。 當應用程式沒有刪除連絡人的許可權時,無論使用者的許可權為何,使用者都無法透過應用程式刪除該連絡人。
  • 安全性是使用規則設定的;每個規則都是 , Grant 並套用至三元: (<ItemSet, PrincipalSet, RightSet>) 。
  • 規則本身會儲存為 Items

取得專案的許可權

每個 WinFS 專案類別都有一個名為 GetRightsForCurrentUser 的方法,它會傳回目前使用者在指定專案上擁有的許可權集:READ、WRITE、DELETE 等等。 此外,方法會傳回 WinFS 允許使用者執行的方法集合。

設定專案的許可權

WinFS 會使用特殊的專案類型 , SecurityRule 在 上 Items 儲存許可權資訊。 因此,設定和變更許可權與在 WinFS 中操作任何其他 Item 許可權並無不同。 以下是示範如何設定資料夾專案許可權的程式碼範例:

using (ItemContext ctx = ItemContext.Open("\\localhost\WinFS_C$")) {
  SecurityRule sr = new SecurityRule (ctx);
  sr.Grant = true;
  // set permission on items under folder1 including folder1
  sr.AppliesTo = <folder1's Identity Key>; 
  sr.Condition = acl1;   // a DACL
  sr.Save();
}

擴充 WinFS API

每個內建 WinFS 類別都包含標準方法,例如 Find* 和 具有取得和設定域值的屬性。 這些類別和相關聯的方法形成 WinFS API 的基礎,並可讓您瞭解如何使用一個類別,一般而言,如何使用許多其他 WinFS 類別。 不過,雖然標準行為很有用,但每個特定資料類型都需要額外的類型特定行為。

定義域行為

除了這些標準方法之外,每個 WinFS 類型通常會有一組專屬於該類型的網域特定方法。 (實際上,WinFS 檔通常會將類型定義稱為 架構,反映 WinFS 的資料庫繼承。) WinFS 會將這些類型特定方法視為 網域行為。 例如,以下是連絡人架構中的一些網域行為:

  • 判斷電子郵件地址是否有效
  • 指定資料夾,取得資料夾的所有成員集合
  • 指定專案識別碼,取得代表這個專案的物件
  • 指定人員,取得其線上狀態
  • 使用協助程式函式建立新的連絡人或暫時連絡人

Value-Added行為

具有領域行為的資料類別形成應用程式開發人員建置的基礎。 不過,資料類別不可能也不想要公開與該資料相關的每個可考慮行為。

您可以提供新的類別,以擴充 WinFS 資料類別所提供的基底功能。 您可以撰寫類別,其方法會採用一或多個 WinFS 資料類別做為參數。 在下列範例中 OutlookMainServices ,和 WindowsMessageServices 是使用標準 WinFS MailMessagePerson 類別的假設類別:

MailMessage m = MailMessage.FindOne (…);
OutlookEMailServices.SendMessage(m); 
 
Person p = Person.FindOne (…);
WindowsMessagerServices wms = new WindowsMessagerServices(p);
wms.MessageReceived += new MessageReceivedHandler (OnMessageReceived);
wms.SendMessage("Hello");

然後,您可以使用 WinFS 註冊這些自訂類別。 註冊資料將會與每個已安裝 WinFS 類型的架構中繼資料 WinFS 相關聯。 WinFS 會將架構中繼資料儲存為 WinFS 專案;因此,您可以更新、查詢和擷取它,就像所有其他 WinFS 專案一樣。

指定條件約束

WinFS 資料模型允許類型的值條件約束。 當您將專案新增至存放區時,WinFS 會評估並強制執行這些條件約束。 不過,您有時想要確認輸入資料符合其條件約束,而不會產生往返伺服器的額外負荷。 WinFS 可讓架構/類型作者決定是否支援用戶端條件約束檢查。 當類型支援用戶端驗證時,類型會有驗證方法,您可以呼叫來驗證物件是否符合指定的條件約束。 請注意,無論開發人員是否呼叫 Validate 方法,WinFS 仍會檢查存放區的條件約束。

使用 WinFS API 和 SQL

WinFS API 可讓開發人員使用熟悉的 Common Language Runtime (CLR) 概念來存取 WinFS 存放區。 在本章中,我針對 WinFS 存取使用了下列程式碼撰寫模式:

  1. 系結至 ItemContext
  2. 尋找所需的專案。
  3. 更新專案。
  4. 將所有變更儲存回存放區。

步驟 2 基本上是存放區的查詢。 WinFS API 會根據 OPath 來指定這些查詢,使用篩選運算式語法。 在許多情況下,使用篩選運算式應該就足以應付大部分的工作。 不過,在某些情況下,開發人員會想要使用 SQL 的完整功能和彈性。

下列功能存在於 SQL 中,但在使用篩選運算式時無法使用:

  • 匯總 (Group ByHaving 、) Rollup
  • 投影 (包括計算的選取運算式、distinct、 IdentityColRowGuidCol)
  • 針對 XML
  • Union
  • 選項
  • 右/全/交叉聯結
  • 巢狀選取專案
  • 聯結至非 WinFS 資料表

因此,WinFS 開發人員必須能夠在 SQLClient API 與 WinFS API 之間順暢地轉換,並在程式碼的各種位置使用其中一個或另一個。

使用 SQL 匯總和分組,然後使用 WinFS API

小型企業擁有者 Joe 想要判斷他前 10 名客戶是誰,並將購物籃傳送給他們。 假設 Customer 是架構化專案類型。 這表示 ISV 已將 Customer 類型的架構提供給 WinFS,因此也表示 WinFS 存放區現在可以包含 Customer 專案。 客戶專案具有架構化訂單專案類型的保存連結。 Order Item 具有 Line Orders 的內嵌集合,如下所示:

1. using (ItemContext ctx = ItemContext.Open()) {
2. 
3.  SqlCommand cmd = ctx.CreateSqlCommand();
4.  cmd.CommandText = 
5.   "select object(c) from Customers c inner join (" +
6.     "select top 10 C.ItemId, sum(p.price) " +
7.     "from Customers C" +
8.     "inner join Links L on L.SourceId = C.ItemId" +
9.   "inner join Orders O on L.TargetId = O.ItemId" + 
10.    "cross join unnest(O.LineOrders) " + 
11.    "group by C.ItemId" +
12.    "order by sum(p.price)) t ON c.ItemId = t.ItemId"; 
13.
14.  SqlDataReader rdr = cmd.ExecuteReader();
15. 
16.  GiftBasketOrder gbOrder = new GiftBasketOrder(Ö);
17. 
18.  while (rdr.Read()) {
19.   Customer c = new Customer((CustomerData) rdr.GetValue(0));
20.   // add the customer to gbOrder's recipient collection
21.   gbOrder.Recipients.Add(c);
22.  }
23.
24.  // send the order. The ISV's GiftBasketOrder can easily pull out 
25.  // customer info such as shipping address from the Customer object
26.  gbOrder.Send();
27. }                                             

在此範例的第 1 行中,我開啟系統磁片區根目錄的內容。 在第 3 行中,我建立 SQL 命令物件,以供後續用來對 WinFS 存放區執行 SQL 查詢。 此命令物件會重複使用專案內容所使用的連接。 第 4 到 12 行會建構查詢,第 14 行會執行查詢。 此查詢會以下列方式傳回前 10 名客戶:第 6 到 12 行的 SELECT 語句會產生包含每個客戶訂單總值的群組資料表;第 12 行上的 ORDER BY 子句與第 6 行的前 10 個修飾詞結合,只會選取此分組資料表中的前 10 名客戶。

類別 GiftBasketOrder 是自訂類別,會使用 WinFS API Customer 物件。 我在第 16 行上建立 的 GiftBasketOrder 實例。

第 19 行會使用 SQLDataReader 讀取傳回之資料列集的第一個 CustomerData 資料行,並將它轉換成 物件。

當您在 WinFS 中定義新的類型 (稱為建立新的架構) 時,您實際上會定義兩種類型:您的 Managed 類別和 WinFS 存放區的永續性類別格式。 WinFS 一律會將 資料 尾碼新增至類別的名稱,以建立存放區類型的名稱。 因此,例如,當您定義位於 WinFS 存放區的新 Customer 類型時,WinFS 會建立平行 CustomerData 的 WinFS 使用者定義類型 (UDT) 。

資料列集的第一個資料行包含存放區 CustomerData 的物件。 我將此物件傳遞至 類別的 Customer 建構函式,而建構函式會從 CustomerData 物件初始化新的 物件。 此範例通常是使用存放區 UDT 來建構 WinFS API 物件。

第 24 行會將客戶新增至 Recipients 的集合。 GiftBasketOrder

最後,我在 Send gbOrder 上使用 方法來「傳送」此訂單。

假設您想要在 10 年的期間內尋找平均薪資 (,) 我的公事包中每個公司的 CEO。 使用下列假設:

  • 我有一個名為 [我的公事包中的公司] 資料夾,其中包含 [組織] 類型的專案。
  • EmployeeData 是以連結為基礎的關聯性,而且具有 YearlyEmploymentHistory 年份和該年份的薪資。
1. using (ItemContext ctx = ItemContext.Open(@"Companies In My Portfolio")) {
2.
3.  SqlCommand cmd = ctx.CreateCommand();
4.  cmd.CommandText = 
5.   "select avg( Salary ) from Links l cross apply " +
6.   "( select Salary from unnest( convert(" + 
7.   "EmployeeData,l.LinkCol)::YearlyEmploymentHistory )" +
8.   "where Year >= '1993' ) where l.LinkID = @LinkID";
9.
10. SqlParameter param = new SqlParameter ("@LinkID", SqlDbType.BigInt);
11. cmd.Parameters.Add (param);
12. 
13. Folder f = Folder.FindByPath (ctx, ".");
14. 
15. FindResult orgs = f.GetMembersOfType (typeof(Organization));
16. foreach (Organization o in orgs) {
17.   EmployeeData ed = EmployeeData.FindEmployeeInRole (o,
18.               Organization.Categories.CeoRole);
19.   param.Value = ed.Link.LinkID;
20.   SqlDataReader rdr = cmd.ExecuteReader ();
21.   rdr.Read ();
22.   Console.WriteLine ("{0} ${1}",   
23.    ((Person)ed.Target).PersonalNames[0].FullName, rdr.GetFloat(0) );
24.   rdr.Close ();
25. }
26. }

第 1 行會開啟 My Portfolio WinFS 共用中的公司內容。 第 3 到 11 行會建立參數化 SQL 查詢,可在資料夾的內容中使用。 此查詢會傳回參數) 所 @LinkID 代表指定員工的平均薪資 (。 第 10 和 11 行指定 為 @LinkID 類型的 BigInt 參數。 我稍後會在第 20 行上執行此查詢。

第 13 行取得 Folder 物件,代表建立內容時所指定共用所指定的資料夾。 第 15 行和第 16 行會設定迴圈,以通過這個資料夾中的物件集合 Organization

針對每個組織,第 17 行會取得 EmployeeData CEO 的物件。

第 19 行會準備查詢,並將 參數的值設定為適當的 LinkID,然後第 20 行會執行參數化的 SELECT。

第 21 行會讀取查詢結果中的下一個和唯一資料列,第 22 和 23 行會列印 CEO 的名稱和 10 年的平均薪資。

總結

WinFS 資料存放區提供比傳統檔案系統更豐富的資料儲存模型。 因為它支援資料、行為和關聯,所以很難將 WinFS 分類為檔案系統、關係資料庫或物件資料庫。 這是一項產品中的所有技術。 WinFS 提供通用資訊的定義,可供在 Longhorn 上執行的所有應用程式全域可見且可供使用。 應用程式可以利用 WinFS 的查詢、擷取、交易式更新和篩選功能;因此,開發人員花費較少的時間來開發資料存取和儲存體程式碼,以及更多時間處理獨特的應用程式功能。

繼續進行第 5 章:資料系結