Partager via


Chapitre 4 : Stockage

 

Introduction
Chapitre 1 : Le modèle d’application « Longhorn »
Chapitre 2 : Création d’une application « Longhorn »
Chapitre 3 : Contrôles et XAML

Chapitre 4 : Stockage

Brent Recteur
Wise Owl Consulting

Janvier 2004

MISE À JOUR : En dépit de ce qui peut être dit dans ce contenu, « WinFS » n’est pas une fonctionnalité qui viendra avec le système d’exploitation Longhorn. Toutefois, « WinFS » sera disponible sur la plateforme Windows à une date ultérieure, c’est pourquoi cet article continue d’être fourni à titre d’information.

Contenu

Qu’est-ce que WinFS ?
Modèle de programmation WinFS
Utilisation de l’API WinFS et de SQL
Résumé

À certains égards, l’ordinateur personnel est un nom inadéquat. La plupart des gens n’utilisent pas d’ordinateur personnel pour calculer. Ils utilisent un ordinateur pour communiquer (par e-mail ou messagerie instantanée) et pour stocker et organiser leurs données personnelles (tels que le courrier électronique, les documents, les images et la musique numérique). Malheureusement, bien que votre ordinateur stocke actuellement ces données assez bien, il fait un travail relativement médiocre pour vous permettre d’organiser les informations afin que vous puissiez les trouver plus tard.

La capacité de disque a augmenté d’environ 70 % par an au cours de la dernière décennie. Il est actuellement possible d’acheter des lecteurs avec plus de 250 gigaoctets (Go) de stockage. Il est probable que des lecteurs de 500 Go seront disponibles dans les prochaines années et que de nombreux systèmes auront plusieurs lecteurs de disque. Je viens de faire un rapide case activée sur l’ordinateur sur lequel j’écris ce chapitre, et j’ai 283 667 fichiers dans 114 129 dossiers en seulement 200 Go d’espace disque. Quand j’oublie exactement où j’ai mis un fichier, il peut prendre un certain temps pour le retrouver. Dans le pire des cas, je dois rechercher l’intégralité du contenu de chaque disque. Dans quelques années, les gens seront en mesure de stocker des millions de fichiers, dont la plupart, si rien ne s’améliore, ils ne verront plus jamais.

L’une des raisons pour lesquelles les gens ont des difficultés à trouver des informations sur leur ordinateur est en raison de la capacité limitée de l’utilisateur à organiser les données. La prise en charge actuelle du système de fichiers pour les dossiers et les fichiers fonctionnait bien à l’origine, car il s’agissait d’un paradigme familier pour la plupart des gens et le nombre de fichiers était relativement faible. Cependant, il ne vous permet pas facilement de stocker une image de votre collègue Bob jouant au softball lors du pique-nique d’entreprise 2007 dans un parc local et de trouver l’image plus tard lors de la recherche de documents qui:

  • Mentionner Bob
  • Impliquer des sports
  • Lien avec les événements de l’entreprise
  • Se rapporter au parc ou à ses environs
  • Ont été créés en 2007

La structure de dossiers hiérarchique ne fonctionne pas correctement lorsque vous souhaitez classer les données de plusieurs façons. Par conséquent, nous avons un problème aujourd’hui dans le sens où nous avons beaucoup de choses à stocker et pas de bon moyen de les classer. Outre la catégorisation des informations, que de nombreuses personnes associent à l’attachement d’un ensemble fixe de mots clés à des données, les utilisateurs doivent associer les données. Par exemple, je pourrais associer une photo au pique-nique de l’entreprise, ou je pourrais lier une photo à Bob, qui est également membre d’un organization auquel je donne du temps et des efforts, en tant que contact.

Un autre problème est que nous stockons les mêmes éléments dans plusieurs emplacements dans plusieurs formats. Les développeurs consacrent beaucoup de temps et d’efforts à créer leurs propres abstractions de stockage uniques pour les informations quotidiennes telles que les Personnes, les lieux, les heures et les événements. Par exemple, Microsoft Outlook a une définition de contact. Le carnet d’adresses Microsoft Windows a également sa propre définition d’un contact. Chaque application de messagerie instantanée en a une autre. Chaque application stocke sa définition d’un contact dans un silo d’informations unique et isolé.

Il existe un certain nombre de problèmes avec les approches actuelles du stockage des données, notamment les suivants :

  • Les développeurs réinventent les abstractions de données de base à plusieurs reprises.
  • Plusieurs applications ne peuvent pas facilement partager des données communes.
  • Les mêmes informations se trouvent dans plusieurs emplacements.
  • L’utilisateur entre à plusieurs reprises les mêmes informations.
  • Les copies distinctes des données ne sont plus synchronisées.
  • Il n’y a aucune notification de modification de données.

Qu’est-ce que WinFS ?

WinFS est le nouveau système de stockage de Longhorn. Il améliore la plateforme Microsoft Windows de trois manières. Tout d’abord, il vous permet de classer vos informations de plusieurs façons et de lier un élément d’information à un autre. Deuxièmement, il fournit un format de stockage commun pour les informations collectées au quotidien, telles que les informations traitant de personnes, de lieux, d’images, etc. Troisièmement, il favorise le partage de données d’informations communes entre plusieurs applications provenant de plusieurs fournisseurs.

WinFS est une plateforme de stockage

WinFS est une plateforme de stockage active permettant d’organiser, de rechercher et de partager toutes sortes d’informations. Cette plateforme définit un modèle de données riche qui vous permet d’utiliser et de définir des types de données riches que la plateforme de stockage peut utiliser. WinFS contient de nombreux schémas qui décrivent des entités réelles telles que images, documents, Personnes, lieux, événements, tâches et messages. Ces entités peuvent être assez complexes. Par exemple, une personne peut avoir plusieurs noms, plusieurs adresses physiques et de messagerie, un emplacement actuel et bien plus encore.

Les éditeurs de logiciels indépendants peuvent également définir leurs propres nouveaux types de données et fournir leur schéma à WinFS. En permettant à WinFS de gérer des problèmes de stockage complexes, un éditeur de logiciels indépendant peut se concentrer sur le développement de sa logique d’application unique et tirer parti des fonctionnalités de stockage plus riches de WinFS pour ses données quotidiennes et personnalisées.

WinFS contient un moteur relationnel qui vous permet de localiser des instances de types de stockage à l’aide de requêtes relationnelles puissantes. WinFS vous permet de combiner ces entités de stockage de manière significative à l’aide de relations. Un contact peut être membre du groupe Employés d’une organisation et simultanément membre du groupe Ménage pour une adresse spécifique. Les éditeurs de logiciels indépendants acquièrent automatiquement la possibilité de rechercher, de répliquer, de sécuriser et d’établir des relations entre leurs types de données uniques ainsi qu’entre les types de données Windows prédéfinis.

Cette structure permet à l’utilisateur de poser des questions au système et de lui demander de localiser des informations plutôt que de demander au système de rechercher individuellement des dossiers. Par exemple, vous pouvez demander à WinFS de rechercher tous les messages électroniques des personnes figurant sur votre liste d’amis de messagerie instantanée pour lesquelles vous n’avez pas de numéro de téléphone. À l’aide de requêtes relationnelles, vous pouvez trouver tous les membres d’un ménage pour un employé particulier ayant un anniversaire dans le mois en cours.

WinFS prend également en charge plusieurs modèles de programmation flexibles qui vous permettent de choisir l’interface de programmation d’application (API) appropriée pour la tâche. Vous pouvez accéder au magasin à l’aide de requêtes relationnelles traditionnelles à l’aide du langage sql (Structured Query Language). Vous pouvez également utiliser des classes et des objets .NET pour accéder au magasin de données. Vous pouvez également utiliser des API XML sur le magasin de données. WinFS prend également en charge l’accès aux données via l’API de système de fichiers Microsoft Win32 traditionnelle. Vous pouvez même mélanger et mettre en correspondance, c’est-à-dire utiliser plusieurs API pour une seule tâche. Toutefois, dans la plupart des cas, les développeurs utilisent les API de classe managée pour modifier les données dans le magasin WinFS. Il est souvent beaucoup plus complexe d’effectuer une mise à jour à l’aide d’instructions SQL brutes que d’utiliser les API d’objet.

En outre, WinFS fournit un ensemble de services de données pour la surveillance, la gestion et la manipulation de vos données. Vous pouvez vous inscrire pour recevoir des événements lorsque des éléments de données particuliers changent. Vous pouvez planifier winFS pour répliquer vos données sur d’autres systèmes.

WinFS est un système de fichiers

Pour les données traditionnelles basées sur des fichiers, telles que les documents texte, les pistes audio et les clips vidéo, WinFS est le nouveau système de fichiers Windows. En règle générale, vous stockez les données main d’un fichier, le flux de fichiers, en tant que fichier sur un volume NTFS. Toutefois, chaque fois que vous appelez une API qui modifie ou ajoute des éléments avec des parties de flux de fichiers NTFS, WinFS extrait les métadonnées du flux et ajoute les métadonnées au magasin WinFS. Ces métadonnées décrivent des informations sur le flux, telles que son chemin, ainsi que toutes les informations que WinFS peut extraire du flux. Selon le contenu du fichier, ces métadonnées peuvent être l’auteur (d’un document), le genre (d’un fichier audio), les mots clés (à partir d’un fichier PDF), etc. WinFS synchronise le flux de fichiers résidents NTFS et les métadonnées résidant dans WinFS. Les nouvelles applications Longhorn peuvent également choisir de stocker leurs flux de fichiers directement dans WinFS. Les flux de fichiers sont accessibles à l’aide de l’API de système de fichiers Win32 existante ou de la nouvelle API WinFS.

WinFS n’est pas juste un système de fichiers

Un système de fichiers gère les fichiers et les dossiers. Bien que WinFS gère les fichiers et les dossiers, il gère également tous les types de données non basées sur les fichiers, tels que les contacts personnels, les calendriers d’événements, les tâches et les messages électroniques. Les données WinFS peuvent être structurées, semi-structurées ou non. Les données structurées incluent un schéma qui définit également à quoi servent les données et comment les utiliser. Étant donné que WinFS est, en partie, un système relationnel, il applique l’intégrité des données en ce qui concerne la sémantique, les transactions et les contraintes.

WinFS n’est pas seulement un système relationnel. Il prend en charge à la fois le stockage hiérarchique et le stockage relationnel. Il prend en charge le retour de données en tant que types structurés et en tant qu’objets ( types plus comportement). Vous pouvez considérer WinFS comme un système de stockage de données hiérarchique, relationnel et orienté objet, bien qu’il contienne en fait certains aspects de chacun de ces systèmes de stockage traditionnels. WinFS s’étend au-delà du système de fichiers traditionnel et du système de base de données relationnelle. Il s’agit du magasin de tous les types de données sur la plateforme Windows la plus récente.

WinFS et NTFS

Vous pouvez stocker un fichier dans le système de fichiers NTFS traditionnel ou dans le nouveau magasin de données WinFS, comme vous pouvez stocker des éléments dans FAT32 ou sur CD-ROMs ou dans NTFS aujourd’hui. Normalement, un fichier stocké dans NTFS n’est pas visible dans WinFS. Les applications Longhorn qui utilisent les nouvelles API WinFS peuvent accéder aux données stockées dans WinFS ou en NTFS. En outre, les applications Longhorn peuvent continuer à utiliser l’API Win32 pour accéder aux données stockées dans le système de fichiers NTFS.

Promotion de fichier

Les fichiers sont dans WinFS ou non. Tout élément qui a une partie de flux de fichiers peut participer à la promotion/rétrogradation, que nous appelons plus généralement gestion des métadonnées. Lorsque WinFS promeut un fichier, il extrait les métadonnées du contenu du fichier NTFS connu et ajoute les métadonnées au magasin de données WinFS. Le flux de données réel du fichier reste dans le système de fichiers NTFS. Vous pouvez ensuite interroger WinFS concernant les métadonnées comme si le fichier se trouve en mode natif dans WinFS. WinFS détecte également les modifications apportées au fichier NTFS et met à jour les métadonnées dans le magasin de données WinFS si nécessaire.

Importation et exportation de fichiers

Vous pouvez également importer un fichier dans WinFS à partir de NTFS et exporter un fichier de WinFS vers NTFS. L’importation et l’exportation d’un fichier déplace à la fois le contenu du fichier et les métadonnées. Après l’importation ou l’exportation, le nouveau fichier est complètement indépendant du fichier d’origine.

Modèle de programmation WinFS

Le modèle de programmation WinFS inclut l’accès aux données, la manipulation des données, l’extensibilité des classes de données WinFS, la synchronisation des données, les notifications de modification de données et la hiérarchisation des événements. L’accès aux données et la manipulation des données vous permettent de créer, récupérer, mettre à jour et supprimer des données stockées dans WinFS et d’exercer des comportements spécifiques à un domaine. L’extensibilité de classe de données vous permet d’étendre les schémas WinFS avec des champs personnalisés et des types personnalisés. La synchronisation des données vous permet de synchroniser des données entre des magasins WinFS et entre un magasin WinFS et un magasin non WinFS.

Le haut de la hiérarchie du modèle de données WinFS est un service WinFS, qui est simplement un instance de WinFS. Un niveau dans la hiérarchie du service est un volume. Un volume est le plus grand conteneur autonome d’éléments. Chaque instance WinFS contient un ou plusieurs volumes. Dans un volume se trouvent des éléments.

WinFS introduit l’élément comme nouvelle unité de cohérence et de fonctionnement, plutôt que comme fichier. Le système de stockage stocke les éléments. Vous disposez d’une capacité de requête enrichie sur les éléments. Un élément est en fait un type de base du système de stockage. Un élément a donc un ensemble d’attributs de données et fournit une fonctionnalité de requête de base.

Personnes généralement organiser les données dans le monde réel en fonction d’un système qui a du sens dans un domaine donné. Tous ces systèmes partitionnent les données en groupes nommés. WinFS modélise cette notion avec le concept d’un dossier. Un dossier est un type spécial d’élément. Il existe deux types de dossiers : les dossiers de confinement et les dossiers virtuels.

Un dossier de confinement est un élément qui contient des liens contenant d’autres éléments et modélise le concept courant d’un dossier de système de fichiers. Un élément existe tant qu’au moins un lien de conservation le référence. Notez qu’un dossier de confinement ne contient pas directement les éléments logiquement présents dans le dossier, mais qu’il contient plutôt des liens vers ces éléments. Cela permet à plusieurs dossiers de confinement de contenir le même élément.

Un dossier virtuel est une collection dynamique d’éléments. Il s’agit d’un ensemble nommé d’éléments. Vous pouvez énumérer le jeu explicitement ou spécifier une requête qui retourne les membres de l’ensemble. Un dossier virtuel spécifié par une requête est très intéressant. Lorsque vous ajoutez un nouvel élément au magasin qui répond aux critères de la requête pour un dossier virtuel, le nouvel élément est automatiquement membre du dossier virtuel. Un dossier virtuel est lui-même un élément. D’un point de vue conceptuel, il représente un ensemble de liens non liés aux éléments, comme vous pouvez le voir dans la figure 4-1.

Figure 4-1. Hiérarchie du modèle de données WinFS

Parfois, vous devez modéliser une notion de confinement très contrainte( par exemple, un document Microsoft Word incorporé dans un message électronique est, dans un sens, lié plus étroitement à son conteneur qu’un fichier contenu dans un dossier. WinFS exprime cette notion à l’aide d’éléments incorporés. Un élément incorporé est un type spécial de lien dans un élément (nommé Embedded Link) qui fait référence à un autre élément. L’élément référencé peut être lié à ou manipulé uniquement dans le contexte de l’élément contenant.

Enfin, WinFS fournit la notion de catégories comme moyen de classer les éléments. Vous pouvez associer une ou plusieurs catégories à chaque élément dans WinFS. WinFS, en effet, étiquette le nom de la catégorie sur l’élément. Vous pouvez ensuite spécifier le nom de la catégorie dans les recherches. Le modèle de données WinFS permet la définition d’une hiérarchie de catégories, ce qui permet une classification arboresculaire des données.

Organisation des informations

Toutes ces fonctionnalités permettent d’organiser vos informations dans WinFS de cinq façons :

  • Organization hiérarchiques basés sur des dossiers. Avec cette approche, vous disposez toujours de la structure traditionnelle de dossier hiérarchique et d’élément organization. Tous les éléments d’un magasin de données WinFS doivent résider dans un conteneur, et l’un de ces types de conteneurs est un dossier.
  • Organization basée sur les types. Un élément est toujours d’un type particulier. Par exemple, vous avez des éléments de personne, des éléments photo, des éléments d’organisation et de nombreux autres types disponibles. Vous pouvez même créer de nouveaux types et les stocker dans le magasin de données WinFS.
  • Organization basée sur des propriétés d’élément. Vous pouvez afficher les éléments dont une ou plusieurs propriétés sont définies sur des valeurs spécifiées. Il s’agit, en fait, d’une vue de dossier virtuel avec une requête qui retourne les éléments avec la valeur spécifiée pour les propriétés spécifiées.
  • organization basées sur les relations. Vous pouvez récupérer des éléments en fonction de leur relation avec d’autres éléments( par exemple, une personne peut être membre d’une organisation, et l’un d’eux peut être organisé ou recherché en termes de cette relation.
  • organization par catégorie. Vous pouvez créer et associer un nombre quelconque de mots clés définis par l’utilisateur à un élément. Vous pouvez ensuite récupérer les éléments qui ont une valeur spécifique pour un mot clé associé. Toutefois, vous ne pourrez pas créer de taxonomies de catégorisation, de sorte que cette technique organization n’est pas aussi puissante que les approches précédentes.

API WinFS

WinFS fournit trois API d’accès aux données : l’API WinFS managée, l’API ADO.NET et l’API Win32. L’API WinFS est une API « de haut niveau » fortement typée. ADO.NET fournit une API de niveau inférieur pour l’utilisation des données en tant que XML ou sous forme de tables ou de lignes. À l’aide de ADO.NET, vous pouvez accéder aux données stockées dans WinFS en utilisant Transact-Structured langage de requête (T-SQL) et, lorsque vous le souhaitez, récupérer des données en XML à l’aide de la fonctionnalité FOR XML de T-SQL. L’API Win32 permet d’accéder aux fichiers et dossiers stockés dans WinFS.

Vous préférerez peut-être utiliser plusieurs modèles d’accès pour résoudre un problème. Par exemple, vous pouvez émettre une requête T-SQL qui retourne un ensemble de contacts en tant qu’objets managés du type Contact WinFS. Quelle que soit l’API que vous utilisez, chaque API manipule en fin de compte les données dans le magasin WinFS à l’aide de T-SQL.

Dans de nombreux cas, vous préférerez utiliser l’API WinFS managée. Ces classes .NET Framework effectuent automatiquement le mappage de relation objet nécessaire pour traduire entre les constructions de programmation orientée objet, et elles exécutent le T-SQL nécessaire pour obtenir l’accès aux données WinFS.

Utilisation des classes WinFS managées

Les classes managées WinFS résident dans l’espace System.Storage de noms et ses espaces de noms imbriqués. De nombreuses applications utilisent également des définitions de type WinFS à partir de l’espace System.Storage.Core de noms. Vous pouvez également utiliser des types à partir d’espaces de noms plus spécialisés. Par exemple, les classes managées qui manipulent la définition système d’un contact résident dans l’espace de System.Storage.Contact noms. Par souci de simplicité, tous les exemples de code de ce chapitre utilisent l’ensemble de using déclarations suivant :

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

ItemContext

Le magasin WinFS se compose d’éléments organisés en dossiers et classés. La première étape de l’utilisation de WinFS consiste à identifier l’ensemble des éléments avec lesquels vous souhaitez travailler. Nous appelons cette liaison de processus, et l’ensemble d’éléments peut être l’un des suivants :

  • Un volume entier (également appelé dossier racine)
  • Sous-ensemble identifiable d’éléments dans un volume donné, par exemple, un dossier de conteneur particulier ou un dossier virtuel
  • Un élément individuel
  • Un partage WinFS (qui identifie un volume, un dossier, un dossier virtuel ou un élément individuel)

Pour établir une liaison à un ensemble d’éléments, vous créez un System.Storage.ItemContext objet et vous le connectez à un magasin de données WinFS. Utilisez la méthode d’assistance statique System.Storage.ItemContext.Open pour créer un ItemContext objet.

Le code suivant crée un ItemContext qui se connecte au volume WinFS local par défaut. La valeur par défaut est le partage \\local-computer-name\DefaultStore :

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

Vous pouvez également passer une chaîne au constructeur pour connecter le contexte de l’élément à un magasin WinFS spécifique. Le code suivant crée un contexte d’élément connecté à un partage WinFS identifié par le partage \\machine\Legal Documents :

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

Veillez à fermer ou à supprimer l’objet de contexte dès que vous avez terminé de l’utiliser, quelles que soient les exceptions. Un ItemContext utilise des ressources non managées importantes, telles qu’une connexion au magasin, que vous devez libérer en temps opportun. Pour rendre les contextes de fermeture aussi pratiques que possible, la ItemContext classe implémente l’interface IDisposable . Par conséquent, vous pouvez utiliser l’instruction C# using comme indiqué dans l’exemple suivant pour libérer ces ressources :

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

Stockage d’un nouvel élément dans un magasin de données WinFS

Chaque élément d’un magasin de données WinFS doit être membre d’un dossier du magasin. Vous obtenez la racine de la hiérarchie de dossiers en appelant la méthode System.Storage.Folder.GetRootFolderstatique extrêmement bien nommée . Toutefois, il existe également plusieurs conteneurs définis par le système pour stocker des données spécifiques à l’application. Vous utilisez souvent l’une des méthodes statiques sur la UserDataFolder classe pour récupérer un dossier dans lequel vous placez ensuite de nouveaux éléments.

Obtention d’un dossier

Dans l’exemple suivant, je recherche le dossier Contacts personnels de l’utilisateur actuel s’il existe et je le crée quand il n’existe pas. Notez qu’il s’agit d’un exemple un peu artificiel : le système crée automatiquement le dossier Contacts personnels d’un utilisateur s’il n’existe pas lorsque l’utilisateur se connecte pour la première fois à un système, mais il me donne l’occasion de montrer comment créer un dossier attendu lorsqu’il n’existe pas.

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();
}

Le code précédent effectue un certain nombre de choses intéressantes. Tout d’abord, j’essaie de localiser un dossier existant contenu dans la hiérarchie des dossiers de données personnelles de l’utilisateur. Je ne recherche pas le dossier par un nom bien connu. Au lieu de cela, je recherche le dossier dans l’arborescence de données personnelles de l’utilisateur qui a été précédemment associée à la catégorie PersonalContactsFolderbien connue . L’interpréteur de commandes affiche ce dossier lorsque vous sélectionnez Mes contacts.

Ce dossier existe normalement déjà, mais quand ce n’est pas le cas, je récupère le dossier racine de la hiérarchie de données de l’utilisateur. Je crée un élément, de type WellKnownFolder, puis une référence à une catégorie connue, la PersonalContactsFolder catégorie . J’ai ensuite défini le type du nouveau dossier sur le PersonalContactsFolder type de catégorie, puis j’ajoute le nouveau dossier à son dossier conteneur, le dossier racine des données personnelles de l’utilisateur. WinFS n’enregistre aucune modification apportée au magasin de données tant que vous n’appelez Update pas le contexte de l’élément (ce que j’oublie régulièrement de faire).

Bien sûr, il s’agit de la façon détaillée de rechercher le dossier Contacts personnels. Je voulais vous montrer comment les choses fonctionnent. Normalement, j’utiliserais le code suivant à la place. La FindMyPersonalContactsFolder méthode recherche le dossier existant.

WellKnownFolder userDataFolder =
         UserDataFolder.FindMyPersonalContactsFolder (ctx);

Création d’un élément

Comme j’ai maintenant le dossier Contacts personnels, il semble approprié de créer un contact dans le dossier. Dans l’exemple suivant, je vais créer un certain nombre de contacts Person et les ajouter au dossier :

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 ();
}

Le code précédent utilise la méthode statique Person.CreatePersonalContact . Cette méthode :

  • Crée un élément Person dans le contexte d’élément spécifié
  • Crée une FolderMember relation avec le nom spécifié qui fait référence à la personne
  • Ajoute la FolderMember relation à la PersonalContactsFoldercollection de Relationship

Je mets ensuite à jour les DisplayNamepropriétés , GivenNameet Surname de l’élément Person. Comme toujours, j’appelle Update sur le contexte de l’élément pour enregistrer les modifications apportées au magasin de données.

Examinons de plus près la CreatePersonalContact méthode. Il équivaut à ceci :

// 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 ();

Éléments de relation

WinFS définit un modèle de données de relation qui vous permet de lier des éléments les uns aux autres. Lorsque vous définissez le schéma pour un type de données, vous pouvez définir zéro ou plusieurs relations dans le cadre du schéma. Par exemple, le schéma folder définit la relation FolderMember . Le schéma d’organisation définit la Employee relation. Pour chaque relation définie, il existe une classe qui représente la relation elle-même. Cette classe est dérivée de la Relationship classe et contient des membres spécifiques au type de relation. Il existe également une classe de collection « virtuelle » fortement typée. Cette classe est dérivée de VirtualRelationshipCollection et permet la création et la suppression d’instances de relation.

Une relation lie un élément source à un élément cible. Dans l’exemple précédent, le dossier Contacts personnels était l’élément source et l’élément Person était l’élément cible. La FolderMember relation indique essentiellement que l’élément Person est lié au dossier Contacts personnels en tant que membre du dossier.

Lorsque vous définissez une relation, vous définissez si la relation maintient l’élément cible dans l’existence (une relation de conservation) ou si elle ne conserve pas l’élément cible dans l’existence d’une relation de référence. Lorsque vous créez une relation de conservation avec un élément cible, WinFS incrémente un nombre de références sur l’élément cible. Lorsque WinFS supprime une relation de conservation, il décrémente le nombre de références sur l’élément cible. Un élément n’existe plus dans le magasin lorsque son nombre de références atteint zéro. WinFS ne modifie jamais le nombre de références de la cible lorsque vous créez ou détruisez une relation de référence à la cible. Par conséquent, l’élément cible peut disparaître du magasin lorsque son nombre de références atteint zéro et la relation peut faire référence à un élément qui n’existe plus.

WinFS définit la FolderMember relation comme une relation de rétention. La plupart des autres classes de relation sont des relations de référence.

Éléments de dossier

Maintenant que vous connaissez les éléments de lien, je peux affiner ma description des éléments de dossier. Un dossier est un élément WinFS qui a une collection d’éléments Link. La cible de chaque élément Link de la collection est membre du dossier . La Folder.Members propriété représente cette collection de liens.

Notez que cela donne à un dossier WinFS beaucoup plus de flexibilité que les dossiers de système de fichiers traditionnels. Les membres d’un dossier peuvent être des éléments de fichier et non-fichier. Plusieurs liens vers un élément particulier peuvent résider simultanément dans de nombreux dossiers. En d’autres termes, plusieurs dossiers peuvent contenir le même élément.

Autres types d’éléments

En règle générale, vous créez d’autres types d’éléments dans le magasin WinFS, comme vous l’avez fait dans les exemples précédents. Chaque type a parfois son propre modèle d’utilisation. Par exemple, nous pouvons avoir des organisations en tant que membres de notre dossier Contacts personnels. Nous allons donc en créer un :

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;
}

Maintenant, nous allons ajouter un employé à ce organization :

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 ();
}

De même, nous pouvons créer des ménages dans nos dossiers Contacts personnels. Notez qu’un ménage n’implique pas une famille. Un ménage peut être un groupe de colocataires. WinFS a un schéma supplémentaire pour les familles, mais je vais laisser cela comme un exercice pour le lecteur.

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);
}

L’exemple précédent utilise un concept que je n’ai pas encore abordé. Notez l’utilisation de la ItemID_Key propriété dans cette ligne de code :

  hhmd.Target_Key = p1.ItemID_Key;

Fondamentalement, la ItemID_Key valeur est une autre façon de référencer un élément dans le magasin WinFS. Nous allons donc examiner les façons de trouver des éléments dans le magasin.

Guide pratique pour rechercher des éléments

Bien sûr, il n’est pas très utile de placer des éléments dans un magasin de données si vous ne pouvez pas les trouver par la suite facilement. La ItemContext classe contient instance méthodes que vous pouvez utiliser pour récupérer des éléments dans un magasin de données WinFS. Vous spécifiez le type d’élément à rechercher et les contraintes spéciales que les éléments retournés doivent respecter. En outre, chaque classe d’élément (par exemple, Person, File, Folder, etc.) contient également des méthodes statiques qui vous permettent de rechercher des éléments de ce type particulier.

La FindAll méthode retourne un ou plusieurs éléments qui correspondent aux critères spécifiés. La ItemContext.FindAll méthode instance vous oblige à spécifier le type des éléments à localiser. En outre, vous pouvez éventuellement spécifier des critères de recherche pour limiter l’étendue de la recherche. Par exemple, le code suivant recherche tous les éléments Person qui ont une DisplayName propriété dont la valeur commence par « Brent ».

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

Sinon, je pourrais utiliser la méthode statique FindAll de la Person classe comme suit :

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

Dans ces deux exemples, la FindAll méthode retourne toujours une collection d’éléments correspondant au type et aux critères spécifiés. Cette collection peut ne contenir aucun élément, mais vous ne recevez pas de référence null pour .FindResult Par conséquent, effectuez toujours une itération sur la collection pour obtenir les éléments trouvés.

Quand vous savez qu’un seul élément correspond au type demandé et aux critères de filtre spécifiés, vous pouvez utiliser la FindOne méthode . Toutefois, soyez prudent : la FindOne méthode lève une exception lorsqu’elle trouve plusieurs éléments correspondant à votre demande.

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

Le deuxième paramètre de chaîne est une expression de filtre qui vous permet de spécifier des contraintes supplémentaires auxquelles les éléments retournés doivent satisfaire. Le format de base de l’expression de filtre est une chaîne au format «<propertyName> <operator> <propertyValue> ».

WinFS appelle l’expression une OPath expression. La syntaxe est similaire, bien que non identique, à la XPath syntaxe d’expression utilisée pour identifier les éléments dans un document XML. Ce fragment de code retourne tous les éléments de fichier pour les fichiers avec une extension de fichier « doc » ou « txt » :

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

Ces expressions peuvent être assez complexes. Par exemple, l’instruction suivante retourne tous les éléments Person qui représentent les employés d’un employeur avec la DisplayName valeur « Principal Avantage » :

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

En voici un autre. Je veux les éléments de la personne où le nom de famille n’est pas « Ranier » et les adresses e-mail ne se terminent pas par . edu ».

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

Identification d’un élément spécifique

Vous devez fréquemment créer des références à des éléments dans le magasin WinFS. Finalement, vous utilisez ces références pour localiser l’élément approprié. Plus tôt dans ce chapitre, je vous ai montré comment utiliser un lien pour référencer un élément. Les liens utilisent une identité conviviale basée sur des chaînes pour la référence, et ce nom de chaîne doit être unique dans le dossier contenant le lien. En d’autres termes, vous avez besoin du dossier et de l’un de ses liens contenus pour identifier l’élément référencé.

Toutefois, vous pouvez créer plusieurs liens avec le même nom de chaîne convivial tant que vous ajoutez les liens vers différents dossiers afin que tous les noms d’un même dossier restent uniques. Notez que ces liens multiples avec le même nom de texte convivial n’ont pas besoin de référencer le même élément cible. Ils le pourraient, mais ils n’ont pas à le faire.

Dans ce cas, la recherche de tous les liens avec un nom de texte convivial spécifique (à l’aide FindAllde , par exemple) retourne plusieurs résultats. Vous devez ensuite examiner la source de chaque lien pour déterminer le dossier contenant, puis déterminer le lien qui fait référence à l’élément souhaité.

Nous avons besoin d’un moyen de référencer n’importe quel élément arbitraire dans le magasin, par exemple, supposons que je veux le 3 287e élément dans le magasin. Heureusement, vous pouvez le faire exactement.

Recherche d’un élément par valeur ItemID_Key

WinFS attribue à chaque élément nouvellement créé un numéro d’identification basé sur un GUID, appelé sa ItemID_Key propriété. Dans la pratique, une valeur est très susceptible d’être ItemID_Key unique pour tous les volumes WinFS. Toutefois, WinFS traite toujours cet identificateur comme s’il n’était unique qu’au sein d’un volume. Vous pouvez utiliser cette valeur unique de volume pour identifier n’importe quel élément d’un volume 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);
}

Fonctionnalités communes

L’API WinFS fournit plusieurs fonctionnalités dans l’ensemble des classes de données. Ces fonctionnalités sont

  • Asynchrony
  • Transactions
  • Notifications
  • Prise en charge des objets blob/flux
  • Curseur et pagination

Asynchrony

L’API WinFS vous permet d’exécuter des requêtes de manière asynchrone. L’API WinFS utilise les modèles de modèle de programmation asynchrone standard .NET.

Transactions

Le magasin WinFS est un magasin transactionnel. WinFS, par conséquent, vous permet d’effectuer des mises à jour transactionnelles du magasin à l’aide des BeginTransactionméthodes , CommitTransactionet AbortTransaction sur l’objet ItemContext , comme illustré dans l’exemple suivant :

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 ();
  }
}

Notifications

Le service de notification WinFS utilise les concepts des abonnements à court et à long terme. Un abonnement à court terme dure jusqu’à ce qu’une application annule l’abonnement ou que l’application se ferme. Un abonnement à long terme survivra au redémarrage de l’application. Les observateurs de l’API WinFS sont un ensemble de classes qui permettent aux applications d’être informées de manière sélective des modifications apportées au magasin WinFS et fournissent des informations d’état qui peuvent être conservées par l’application pour prendre en charge les scénarios de suspension/reprise.

La Watcher classe peut informer votre application des modifications apportées à différents aspects des objets WinFS, notamment les éléments suivants :

  • Modifications d’élément
  • Modifications d’élément incorporées
  • Modifications de l’extension d’élément
  • Changements de relation

Lorsqu’un observateur déclenche un événement, il envoie les données d’état de l’observateur avec la notification d’événement. Votre application peut stocker ces données d’état pour une récupération ultérieure. Par la suite, vous pouvez utiliser ces données d’état observateur pour indiquer à WinFS que vous souhaitez recevoir des événements pour toutes les modifications qui se sont produites après la génération de l’état.

Le modèle de programmation observateur permet également de désactiver toute combinaison d’événements ajoutés, modifiés et supprimés. Il peut également être configuré pour déclencher un événement initial qui simule l’ajout de tous les éléments existants, les extensions d’éléments, les relations, etc.

La conception de l’observateur WinFS est divisée en classes décrites dans le tableau suivant.

Classe Objectif/Description
WatcherOptions Classe permettant de spécifier les options initiales d’étendue et de granularité pour StoreWatcher
StoreWatcher Classe quintessentiale pour l’observation des éléments WinFS, des éléments incorporés, des extensions d’élément et des relations
WatcherState Objet opaque qui peut être utilisé pour initialiser un objet StoreWatcher
ChangedEventHandler Classe qui définit le gestionnaire d’événements à appeler par StoreWatcher
ChangedEventArgs Classe passée en tant qu’argument à ChangedEventHandler
ItemChangeDetail Classe de base qui fournit des détails de modification granulaires pour les événements d’élément
ItemExtensionChangeDetail Classe dérivée de ItemChangeDetail qui fournit des détails de modification supplémentaires spécifiques aux événements d’extension d’élément
RelationshipChangeDetail Classe dérivée de ItemChangeDetail qui fournit des détails de modification supplémentaires spécifiques aux événements de relation

Vous utilisez la StoreWatcher classe pour créer un observateur pour un élément dans le magasin WinFS. Le StoreWatcher instance déclenche des événements lorsque l’élément spécifié change. Vous pouvez spécifier le type d’élément et la hiérarchie à watch. Par défaut, un observateur

  • Ne déclenche pas d’événement initial pour établir l’état actuel
  • Surveille l’élément et la hiérarchie (y compris les enfants immédiats) pour toute modification
  • Déclenche des événements d’ajout, de suppression et de modification sur cet élément ou sur n’importe quel enfant dans toute la hiérarchie
  • Déclenche des événements d’ajout, de suppression et de modification pour les extensions d’élément sur cet élément ou sur n’importe quel enfant dans toute la hiérarchie
  • Déclenche des événements d’ajout, de suppression et de modification pour les relations dans lesquelles cet élément ou n’importe quel enfant de la hiérarchie entière est la source de la relation

Étant donné que par défaut, un observateur surveille les modifications apportées à l’élément spécifié et à ses descendants, vous pouvez spécifier WatchItemOnly comme option observateur. L’exemple suivant recherche uniquement les modifications apportées à l’élément Person situé :

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

Un dossier est simplement un autre élément WinFS. Vous watch pour les modifications apportées à un dossier de la même façon que pour une personne :

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

Vous pouvez également watch pour les modifications apportées à une relation spécifiée d’un élément :

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;
  }
}

Prise en charge des objets blob et des flux

Les API de prise en charge des objets blob et des flux sont toujours en mouvement au moment de la rédaction de cet article. Consultez la documentation pour obtenir les dernières informations sur l’accès aux objets blob et aux flux dans le magasin WinFS.

Curseur et pagination

Les différentes Find méthodes des classes WinFS peuvent retourner une (potentiellement) grande collection d’objets. Cette collection est l’équivalent d’un ensemble de lignes dans le monde de la base de données. Les applications de base de données traditionnelles utilisent un curseur paginé pour naviguer efficacement dans un ensemble de lignes volumineux. Ce curseur fait référence à une seule ligne (un curseurmince) ou à un ensemble de lignes (un curseur de page). L’idée est que les applications récupèrent la valeur d’une page de lignes à la fois ; ils peuvent également identifier une ligne dans la page pour la mise à jour et la suppression positionnées. L’API WinFS fournit des abstractions similaires au développeur pour traiter des collections volumineuses.

Par défaut, une opération de recherche fournit un curseur dynamique en lecture seule, défilementable et sur la collection retournée. Une application peut avoir un curseur de tuyau d’incendie pour des performances maximales. Un curseur de tuyau d’incendie est un curseur avant uniquement. L’application peut récupérer une page de lignes à la fois, mais l’opération de récupération suivante commencera par l’ensemble de lignes suivant. Elle ne peut pas revenir en arrière et récupérer à nouveau des lignes. Dans un sens, les lignes circulent du magasin à l’application comme l’eau d’un tuyau d’incendie, d’où le nom.

La CursorType propriété de la FindParameters classe permet à une application de choisir entre un tuyau d’incendie et un curseur avec défilement. Pour les tuyaux d’incendie et les curseurs avec défilement, l’application peut définir une taille de page à l’aide de la PageSize propriété de la FindParameters classe . Par défaut, la taille de page est définie sur 1.

Liaison de données

Vous pouvez utiliser les classes de données WinFS comme sources de données dans un environnement de liaison de données. Les classes WinFS implémentent IDataEntity des interfaces (pour des objets uniques) et IDataCollection (pour les collections). L’interface IDataEntity fournit des notifications à la cible de liaison de données des modifications apportées aux propriétés dans l’objet de source de données. L’interface IDataCollection permet de déterminer le type de base d’un objet dans une collection polymorphe. Il vous permet également de récupérer un System.Windows.Data.CollectionManager, qui navigue dans les entités de données de la collection et fournit une vue (par exemple, ordre de tri ou filtre) de la collection. J’aborde la liaison de données en détail dans le chapitre 5.

Sécurité

Le modèle de sécurité WinFS accorde fondamentalement un ensemble de Rights à un Principal sur un Item des manières suivantes :

  • La sécurité est définie au niveau de Items.
  • Un ensemble de droits peut être accordé à un principe de sécurité sur un Item. Cet ensemble comprend : READ, WRITE, DELETE, EXECUTE (pour tous les éléments), CREATE_CHILD, ADMINISTER et AUDIT. (Des droits supplémentaires peuvent être accordés sur les éléments de dossier.)
  • Les utilisateurs et les applications sont les principes de sécurité. Les droits d’application remplacent les droits utilisateur. Lorsqu’une application n’est pas autorisée à supprimer un contact, un utilisateur ne peut pas le supprimer via l’application, quelles que soient les autorisations de l’utilisateur.
  • La sécurité est définie à l’aide de règles ; chaque règle est un Grant et s’applique à un triplet : (<ItemSet, PrincipalSet, RightSet>).
  • Les règles sont elles-mêmes stockées sous la forme Items.

Obtention de droits sur un élément

Chaque classe d’élément WinFS a une méthode nommée GetRightsForCurrentUser, qui retourne l’ensemble des droits (READ, WRITE, DELETE, etc.) dont dispose l’utilisateur actuel sur l’élément spécifié. En outre, la méthode retourne l’ensemble des méthodes que WinFS permet à l’utilisateur d’exécuter.

Définition de droits sur un élément

WinFS utilise un type d’élément spécial, SecurityRule, pour stocker les informations d’autorisations sur Items. Par conséquent, la définition et la modification des droits ne sont pas différentes de la manipulation d’autres Item droits dans WinFS. Voici un exemple de code montrant comment définir des droits sur un élément de dossier :

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();
}

Extension de l’API WinFS

Chaque classe WinFS intégrée contient des méthodes standard telles que Find* et possède des propriétés permettant d’obtenir et de définir des valeurs de champ. Ces classes et méthodes associées constituent la base des API WinFS et vous permettent d’apprendre à utiliser une classe et de savoir, en général, comment utiliser de nombreuses autres classes WinFS. Toutefois, bien que le comportement standard soit utile, chaque type de données spécifique a besoin de comportements supplémentaires spécifiques au type.

Comportements de domaine

En plus de ces méthodes standard, chaque type WinFS a généralement un ensemble de méthodes spécifiques à un domaine propre à ce type. (En fait, la documentation WinFS fait souvent référence aux définitions de type en tant que schéma, reflétant l’héritage de base de données de WinFS.) WinFS fait référence à ces méthodes spécifiques au type en tant que comportements de domaine. Par exemple, voici quelques comportements de domaine dans le schéma des contacts :

  • Déterminer si une adresse de messagerie est valide
  • Dans un dossier, obtenir la collection de tous les membres du dossier
  • Avec un ID d’élément, obtention d’un objet représentant cet élément
  • Donné à une personne, obtenir son status en ligne
  • Création d’un contact ou d’un contact temporaire avec des fonctions d’assistance

comportements Value-Added

Les classes de données avec des comportements de domaine forment une base sur laquelle les développeurs d’applications s’appuient. Toutefois, il n’est ni possible ni souhaitable que les classes de données exposent tous les comportements concevables liés à ces données.

Vous pouvez fournir de nouvelles classes qui étendent les fonctionnalités de base offertes par les classes de données WinFS. Pour ce faire, écrivez une classe dont les méthodes prennent une ou plusieurs classes de données WinFS en tant que paramètres. Dans l’exemple suivant, et OutlookMainServicesWindowsMessageServices sont des classes hypothétiques qui utilisent les classes et WinFS MailMessage standard Person :

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

Vous pouvez ensuite inscrire ces classes personnalisées avec WinFS. Les données d’inscription sont associées aux métadonnées de schéma que WinFS gère pour chaque type WinFS installé. WinFS stocke vos métadonnées de schéma en tant qu’éléments WinFS ; Par conséquent, vous pouvez le mettre à jour, l’interroger et le récupérer comme vous le feriez pour tous les autres éléments WinFS.

Spécification de contraintes

Le modèle de données WinFS autorise les contraintes de valeur sur les types. WinFS évalue et applique ces contraintes lorsque vous ajoutez des éléments au magasin. Toutefois, vous souhaitez parfois vérifier que les données d’entrée répondent à leurs contraintes sans entraîner la surcharge d’un aller-retour vers le serveur. WinFS permet à l’auteur de schéma/type de décider si le type prend en charge la vérification des contraintes côté client. Lorsqu’un type prend en charge la validation côté client, le type a une méthode validate que vous pouvez appeler pour vérifier qu’un objet satisfait aux contraintes spécifiées. Notez que, que le développeur appelle ou non la Validate méthode , WinFS vérifie toujours les contraintes dans le magasin.

Utilisation de l’API WinFS et de SQL

L’API WinFS permet à un développeur d’accéder au magasin WinFS à l’aide de concepts clr (Common Language Runtime) familiers. Tout au long de ce chapitre, j’ai utilisé le modèle de codage suivant pour l’accès WinFS :

  1. Lier à un ItemContext.
  2. Recherchez les éléments souhaités.
  3. Mettez à jour les éléments.
  4. Enregistrez toutes les modifications dans le magasin.

L’étape 2 est essentiellement une requête vers le magasin. L’API WinFS utilise une syntaxe d’expression de filtre basée sur OPath pour spécifier ces requêtes. Dans de nombreux cas, l’utilisation d’expressions de filtre doit être suffisante pour la plupart des tâches. Toutefois, dans certains cas, le développeur souhaite utiliser toute la puissance et la flexibilité de SQL.

Les fonctionnalités suivantes sont présentes dans SQL, mais elles ne sont pas disponibles lors de l’utilisation d’une expression de filtre :

  • Agrégation (Group By, Having, Rollup)
  • Projection (y compris les expressions de sélection calculées, distinct, IdentityCol, RowGuidCol)
  • Pour XML
  • Union
  • Option
  • Jointure droite/complète/croisée
  • Sélections imbriquées
  • Joindre à une table non-WinFS

Il est donc essentiel qu’un développeur WinFS puisse effectuer une transition transparente entre l’API SQLClient et l’API WinFS, en utilisant l’un ou l’autre à différents endroits du code.

Agréger et regrouper avec SQL, puis utiliser l’API WinFS

Un propriétaire de petite entreprise, Joe, veut déterminer qui sont ses 10 premiers clients et leur envoyer des paniers-cadeaux. Supposons que Customer soit un type d’élément schématisé. Cela signifie qu’un éditeur de logiciels indépendant a fourni un schéma pour le type Client à WinFS. Par conséquent, cela signifie également qu’un magasin WinFS peut désormais contenir des éléments Customer. Un élément Client a un lien de conservation vers un type d’élément de commande schématisé. Order Item a une collection incorporée de commandes de ligne, comme suit :

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. }                                             

À la ligne 1 de cet exemple, j’ouvre un contexte pour la racine du volume système. À la ligne 3, je crée un objet de commande SQL que j’utilise par la suite pour exécuter une requête SQL sur le magasin WinFS. Cet objet de commande réutilise la connexion utilisée par le contexte d’élément. Les lignes 4 à 12 construisent la requête, et la ligne 14 exécute la requête. La requête retourne les 10 premiers clients de la manière suivante : l’instruction SELECT des lignes 6 à 12 génère une table groupée contenant la valeur totale des commandes de chaque client ; la clause ORDER BY à la ligne 12, combinée avec le modificateur TOP 10 à la ligne 6, sélectionne uniquement les 10 premiers clients de cette table groupée.

La GiftBasketOrder classe est une classe personnalisée qui utilise l’objet API Customer WinFS. Je crée un instance de sur la GiftBasketOrder ligne 16.

La ligne 19 utilise pour SQLDataReader lire la première colonne de l’ensemble de lignes retourné et la caste en objet CustomerData .

Lorsque vous définissez un nouveau type dans WinFS (appelé création d’un schéma), vous définissez en fait deux types : votre classe managée et le format persistant de la classe du magasin WinFS. WinFS ajoute toujours le suffixe Données au nom de votre classe pour créer le nom du type du magasin. Par conséquent, par exemple, lorsque vous définissez un nouveau type client qui réside dans le magasin WinFS, WinFS crée le type défini par l’utilisateur (UDT) WinFS parallèle CustomerData .

La première colonne de l’ensemble de lignes contient l’objet du CustomerData magasin. Je passe cet objet au constructeur de la Customer classe et le constructeur initialise le nouvel objet à partir de l’objet CustomerData . Cet exemple est typique de l’utilisation d’UDT de magasin pour construire des objets API WinFS.

La ligne 24 ajoute le client à la Recipients collection du GiftBasketOrder.

Enfin, j’utilise la Send méthode sur gbOrder pour « envoyer » cette commande.

Supposons que vous souhaitiez trouver le salaire moyen (sur une période de 10 ans) pour le pdg de chaque entreprise de mon portefeuille. Utilisez les hypothèses suivantes :

  • J’ai un dossier nommé Entreprises dans mon portefeuille, qui contient des éléments de type Organisation.
  • EmployeeData est une relation basée sur des liens, et elle a une YearlyEmploymentHistory qui a l’année et le salaire pour cette année.
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. }

La ligne 1 ouvre un contexte pour l’action WinFS Companies In My Portfolio. Les lignes 3 à 11 créent une requête SQL paramétrable que je peux utiliser dans le contexte du dossier. Cette requête retourne le salaire moyen d’un employé donné (représenté par le @LinkID paramètre). Les lignes 10 et 11 spécifient que @LinkID est un paramètre de type BigInt. J’exécute cette requête plus loin dans l’exemple, à la ligne 20.

La ligne 13 obtient un Folder objet qui représente le dossier indiqué par le partage que j’ai spécifié lors de la création du contexte. Les lignes 15 et 16 configurent la boucle pour parcourir la collection d’objets de Organization ce dossier.

Pour chaque organization, la ligne 17 obtient l’objet EmployeeData pour le PDG.

La ligne 19 prépare la requête et définit la valeur du paramètre sur le LinkID approprié, puis la ligne 20 exécute le paramètre SELECT paramétré.

La ligne 21 lit la ligne suivante et seule du résultat de la requête, et les lignes 22 et 23 impriment le nom du pdg et le salaire moyen sur 10 ans.

Résumé

Le magasin de données WinFS fournit un modèle de stockage de données beaucoup plus riche que les systèmes de fichiers traditionnels. Étant donné qu’il prend en charge les données, le comportement et les relations, il est difficile de catégoriser WinFS en tant que système de fichiers, base de données relationnelle ou base de données d’objets. Il s’agit d’un peu de toutes ces technologies dans un seul produit. WinFS fournit une définition commune des informations omniprésentes qui sont globalement visibles et disponibles pour toutes les applications s’exécutant sur Longhorn. Les applications peuvent tirer parti des fonctionnalités de requête, d’extraction, de mise à jour transactionnelle et de filtrage de WinFS ; par conséquent, le développeur passe moins de temps à développer le code d’accès aux données et de stockage, et plus de temps à travailler sur des fonctionnalités d’application uniques.

Passez au chapitre 5 : Liaison de données