Глава 4. Хранилище
Введение
Глава 1. Модель приложения Longhorn
Глава 2. Создание приложения Longhorn
Глава 3. Элементы управления и XAML
Глава 4. Хранилище
Брент Проректор
Мудрая Сова Консалтинг
Январь 2004 г.
ОБНОВЛЕНИЕ: Несмотря на то, что может быть указано в этом содержимом, "WinFS" не является функцией, которая будет поставляется с операционной системой Longhorn. Тем не менее, "WinFS" будет доступен на платформе Windows в будущем, поэтому эта статья по-прежнему предоставляется для ваших сведений.
Содержимое
Что такое WinFS?
Модель программирования WinFS
Использование API WinFS и SQL
Сводка
В некотором смысле , персональный компьютер является недостаточным именем. Большинство людей не используют персональный компьютер для вычислений. Они используют компьютер для общения (с помощью электронной почты или обмена мгновенными сообщениями), а также для хранения и упорядочения своих персональных данных (таких как электронная почта, документы, фотографии и цифровая музыка). К сожалению, в то время как ваш компьютер в настоящее время хранит эти данные довольно хорошо, он выполняет относительно плохую работу, позволяя вам упорядочить информацию так, чтобы вы могли найти ее позже.
За последнее десятилетие емкость дисков растет примерно на 70 процентов в год. В настоящее время можно приобрести диски с хранилищем размером более 250 гигабайт (ГБ). Вполне вероятно, что диски емкостью 500 ГБ станут доступны в ближайшие несколько лет, а во многих системах будет несколько дисков. Я только что сделал быстрый проверка на компьютере, на котором я пишу эту главу, и у меня 283 667 файлов в 114 129 папках только в 200 ГБ дискового пространства. Когда я забуду точно, куда я положил файл, это может занять много времени, чтобы найти его снова. В худшем случае приходится искать все содержимое каждого диска. Через несколько лет люди смогут хранить миллионы файлов, большинство из которых, если ничего не улучшится, они никогда не увидят больше.
Одна из причин, по которой люди испытывают трудности с поиском информации на своем компьютере, заключается в ограниченной способности пользователя упорядочивать данные. Текущая поддержка файловой системы для папок и файлов изначально работала хорошо, так как она была знакома большинству людей и количество файлов было относительно небольшим. Тем не менее, это не позволяет вам хранить изображение вашего коллеги Боба играет в софтбол на пикнике 2007 компании в местном парке, а затем найти изображение при поиске документов, которые:
- Упомяните Боба
- Заниматься спортом
- Связь с событиями компании
- Относится к парку или его окрестностям
- Созданы в 2007 году
Иерархическая структура папок работает неправильно, если требуется классифицировать данные различными способами. Таким образом, у нас есть проблема сегодня в том, что у нас есть много вещей для хранения и нет хорошего способа классифицировать его. Помимо классификации информации, которую многие люди связывают с присоединением фиксированного набора ключевых слов к данным, людям необходимо связать данные. Например, я могу связать фотографию с пикником компании или связать фотографию с Бобом, который также является членом организации, которой я отдаю время и усилия, в качестве контакта.
Другая проблема заключается в том, что мы храним одни и те же материалы в нескольких местах в нескольких форматах. Разработчики тратят много времени и усилий на создание собственных уникальных абстракций хранилища для повседневной информации, такой как Люди, места, время и события. Например, в Microsoft Outlook есть определение Contact. Адресная книга Microsoft Windows также имеет собственное определение контакта. Каждое приложение для обмена мгновенными сообщениями имеет еще одно. Каждое приложение хранит свое определение контакта в уникальном изолированном хранилище информации.
Существует ряд проблем с текущими подходами к хранению данных, в том числе следующие:
- Разработчики повторно изобретают основные абстракции данных.
- Несколько приложений не могут легко совместно использовать общие данные.
- Одни и те же сведения находятся в нескольких расположениях.
- Пользователь неоднократно вводит одни и те же сведения.
- Отдельные копии данных становятся несинхронизированными.
- Уведомления об изменении данных отсутствуют.
Что такое WinFS?
WinFS — это новая система хранения в Longhorn. Она улучшает платформу Microsoft Windows тремя способами. Во-первых, это позволяет классифицировать данные несколькими способами и связывать один элемент информации с другим. Во-вторых, он предоставляет общий формат хранения информации, собираемой на повседневной основе, например информации о людях, местах, изображениях и т. д. В-третьих, это способствует обмену общей информацией между несколькими приложениями от нескольких поставщиков.
WinFS — это платформа хранилища
WinFS — это активная платформа хранения для организации, поиска и совместного использования всех видов информации. Эта платформа определяет многофункциональную модель данных, которая позволяет использовать и определять расширенные типы данных, которые может использовать платформа хранения. WinFS содержит множество схем, описывающих реальные сущности, такие как изображения, документы, Люди, места, события, задачи и сообщения. Эти сущности могут быть довольно сложными. Например, у человека может быть несколько имен, несколько физических адресов и адресов электронной почты, текущее расположение и многое другое.
Независимые поставщики программного обеспечения (ISV) также могут определять собственные новые типы данных и предоставлять свою схему в WinFS. Позволяя WinFS управлять сложными проблемами с хранилищем, независимого поставщика программного обеспечения может сосредоточиться на разработке своей уникальной логики приложений и использовать более широкие возможности хранения WinFS для повседневных и пользовательских данных.
WinFS содержит реляционную подсистему, которая позволяет находить экземпляры типов хранилищ с помощью мощных реляционных запросов. WinFS позволяет объединять эти сущности хранилища значимыми способами с помощью связей. Один контакт может быть членом группы сотрудников организации, а одновременно членом группы домашних хозяйств по определенному адресу. Поставщики программного обеспечения автоматически получают возможность поиска, репликации, защиты и установления связей между их уникальными типами данных, а также между предопределенными типами данных Windows.
Эта структура позволяет пользователю задавать системе вопросы и предлагать ей найти информацию, а не запрашивать систему для поиска папок по отдельности. Например, вы можете попросить WinFS найти все сообщения электронной почты от людей в списке приятелей для обмена мгновенными сообщениями, для которых у вас нет номера телефона. С помощью реляционных запросов можно найти всех членов семьи для конкретного сотрудника с днем рождения в текущем месяце.
WinFS также поддерживает несколько гибких моделей программирования, которые позволяют выбрать соответствующий программный интерфейс (API) для задачи. Доступ к хранилищу можно получить с помощью традиционных реляционных запросов с использованием языка структурированных запросов (SQL). Кроме того, для доступа к хранилищу данных можно использовать классы и объекты .NET. Вы также можете использовать API на основе XML в хранилище данных. WinFS также поддерживает доступ к данным через традиционный API файловой системы Microsoft Win32. Вы даже можете смешивать и сопоставлять, то есть использовать несколько API для одной задачи. Однако в большинстве случаев разработчики будут использовать API управляемого класса для изменения данных в хранилище WinFS. Зачастую бывает гораздо сложнее выполнить обновление с помощью необработанных инструкций SQL по сравнению с api-интерфейсами объектов.
Кроме того, WinFS предоставляет набор служб данных для мониторинга, управления ими и управления ими. Вы можете зарегистрироваться для получения событий при изменении определенных элементов данных. Вы можете запланировать репликацию данных в другие системы в WinFS.
WinFS — файловая система
Для традиционных файловых данных, таких как текстовые документы, звуковые дорожки и видеоклипы, WinFS является новой файловой системой Windows. Как правило, main данные файла, файлового потока, хранятся в виде файла на томе NTFS. Однако при каждом вызове API, который изменяет или добавляет элементы с помощью частей файлового потока NTFS, WinFS извлекает метаданные из потока и добавляет метаданные в хранилище WinFS. Эти метаданные описывают сведения о потоке, например его путь, а также любые сведения, которые WinFS может извлечь из потока. В зависимости от содержимого файла эти метаданные могут быть автором (документа), жанром (звукового файла), ключевыми словами (из PDF-файла) и т. д. WinFS синхронизирует файловый поток, резидентный NTFS, и метаданные, резидентные WinFS. Новые приложения Longhorn также могут хранить свои файловые потоки непосредственно в WinFS. Доступ к файловых потокам можно получить с помощью существующего API файловой системы Win32 или нового API WinFS.
WinFS — это не просто файловая система
Файловая система управляет файлами и папками. Хотя WinFS управляет файлами и папками, она также управляет всеми типами данных, не основанными на файлах, такими как личные контакты, календари событий, задачи и сообщения электронной почты. Данные WinFS могут быть структурированными, полуструктурированными или неструктурированными. Структурированные данные включают схему, которая дополнительно определяет, для чего нужны данные и как их использовать. Так как WinFS отчасти является реляционной системой, она обеспечивает целостность данных в отношении семантики, транзакций и ограничений.
WinFS — это не просто реляционная система. Он поддерживает как иерархическое, так и реляционное хранилище. Он поддерживает возврат данных в виде структурированных типов и объектов, а также в виде типов, а также поведения. Вы можете считать WinFS иерархической, реляционной объектно-ориентированной системой хранения данных, хотя на самом деле она содержит определенные аспекты каждой из этих традиционных систем хранения. WinFS выходит за рамки традиционной файловой системы и системы реляционных баз данных. Это хранилище для всех типов данных на новейшей платформе Windows.
WinFS и NTFS
Вы можете хранить файл в традиционной файловой системе NTFS или в новом хранилище данных WinFS так же, как в FAT32, CD-ROMs или NTFS. Обычно файл, хранящийся в NTFS, не отображается в WinFS. Приложения Longhorn, использующие новые API WinFS, могут получать доступ к данным, хранящимся в WinFS или NTFS. Кроме того, приложения Longhorn могут продолжать использовать API Win32 для доступа к данным, хранящимся в файловой системе NTFS.
Повышение уровня файла
Файлы находятся в WinFS или нет. Любой элемент, имеющий часть потока файлов, может участвовать в повышении или понижении уровня, что обычно называется обработкой метаданных. Когда WinFS повышает уровень файла, он извлекает метаданные из известного содержимого файла NTFS и добавляет метаданные в хранилище данных WinFS. Фактический поток данных файла остается в файловой системе NTFS. Затем можно запросить у WinFS метаданные, как если бы файл изначально находится в WinFS. WinFS также обнаруживает изменения в файле NTFS и при необходимости обновляет метаданные в хранилище данных WinFS.
Импорт и экспорт файлов
Вы также можете импортировать файл в WinFS из NTFS и экспортировать файл из WinFS в NTFS. При импорте и экспорте файла перемещается содержимое файла и метаданные. После импорта или экспорта новый файл полностью независим от исходного файла.
Модель программирования WinFS
Модель программирования WinFS включает доступ к данным, обработку данных, расширяемость класса данных WinFS, синхронизацию данных, уведомления об изменении данных и определение приоритетов событий. Доступ к данным и обработка данных позволяют создавать, извлекать, обновлять и удалять данные, хранящиеся в WinFS, а также осуществлять поведение, зависящее от домена. Расширяемость класса данных позволяет расширить схемы WinFS с помощью настраиваемых полей и настраиваемых типов. Синхронизация данных позволяет синхронизировать данные между хранилищами WinFS и между WinFS и хранилищем, не относящихся к WinFS.
Верхней частью иерархии модели данных WinFS является служба WinFS, которая является просто экземпляром WinFS. Одним из уровней иерархии службы является том. Том — это самый большой автономный контейнер элементов. Каждый экземпляр WinFS содержит один или несколько томов. В томе находятся элементы.
WinFS представляет элемент как новую единицу согласованности и операций, а не файл. В системе хранения хранятся элементы. У вас есть широкие возможности выполнения запросов к элементам. Элемент фактически является базовым типом системы хранения. Таким образом, элемент имеет набор атрибутов данных и предоставляет базовую возможность запроса.
Люди обычно упорядочивать данные в реальном мире в соответствии с какой-то системой, которая имеет смысл в заданной области. Все такие системы разделяют данные на именованные группы. WinFS моделирует это понятие с концепцией папки. Папка — это особый тип элемента. Существует два типа папок: автономные папки и виртуальные папки.
Вложенная папка — это элемент, который содержит ссылки на другие элементы и моделирует общую концепцию папки файловой системы. Элемент существует до тех пор, пока на него ссылается хотя бы одна удерживаемая ссылка. Обратите внимание, что папка вложенности не содержит непосредственно элементы, логически присутствующих в папке, а содержит ссылки на эти элементы. Это позволяет нескольким автономным папкам содержать один и тот же элемент.
Виртуальная папка — это динамическая коллекция элементов. Это именованный набор элементов. Можно либо перечислить набор явным образом, либо указать запрос, возвращающий члены набора. Виртуальная папка, указанная запросом, довольно интересна. При добавлении в хранилище нового элемента, соответствующего критериям запроса виртуальной папки, новый элемент автоматически становится членом виртуальной папки. Виртуальная папка сама по себе является элементом. По сути, он представляет собой набор ссылок на элементы, как показано на рисунке 4-1.
Рис. 4-1. Иерархия модели данных WinFS
Иногда необходимо смоделировать понятие вложенности с большими ограничениями, например, документ Microsoft Word, внедренный в сообщение электронной почты, в каком-то смысле более тесно привязан к контейнеру, чем, например, файл, содержащийся в папке. WinFS выражает это понятие с помощью внедренных элементов. Внедренный элемент — это особый вид ссылки в элементе (с именем Внедренная ссылка), которая ссылается на другой элемент. Элемент, на который указывает ссылка, может быть привязан к элементу или иным образом управляться только в контексте содержащего элемента.
Наконец, WinFS предоставляет понятие категорий как способ классификации элементов. Вы можете связать одну или несколько категорий с каждым элементом в WinFS. WinFS, по сути, добавляет имя категории к элементу. Затем можно указать имя категории в поисковых запросах. Модель данных WinFS позволяет определение иерархии категорий, что обеспечивает древовидную классификацию данных.
Упорядочение информации
Все эти функции вместе позволяют организовать информацию в WinFS пятью способами:
- Иерархическая организация на основе папок. При таком подходе у вас по-прежнему будет традиционная иерархическая структура организации папок и элементов. Все элементы в хранилище данных WinFS должны находиться в контейнере, и одним из этих типов контейнеров является папка.
- Организация на основе типов. Элемент всегда имеет определенный тип. Например, у вас есть элементы person, photo items, organization items и многие другие доступные типы. Вы даже можете создавать новые типы и хранить их в хранилище данных WinFS.
- Организация на основе свойств элемента. Вы можете просматривать элементы, для которых для одного или нескольких свойств заданы указанные значения. Это, по сути, представление виртуальной папки с запросом, который возвращает элементы с указанным значением для указанных свойств.
- Организация на основе отношений. Вы можете получать элементы на основе их связи с другими элементами, например, пользователь может быть членом организации, и его можно упорядочить или найти с точки зрения этой связи.
- Организация на основе категорий. Вы можете создать и связать любое количество определяемых пользователем ключевых слов с элементом. Впоследствии можно получить элементы, имеющие определенное значение для связанного ключевое слово. Однако вы не сможете создавать классификации классификаций, поэтому этот метод организации не так эффективен, как предыдущие подходы.
API WinFS
WinFS предоставляет три API доступа к данным: управляемый API WinFS, API ADO.NET и API Win32. API WinFS — это строго типизированный "высокоуровневый" API. ADO.NET предоставляет БОЛЕЕ низкий уровень API для работы с данными в виде XML, таблиц или строк. С помощью ADO.NET можно получить доступ к данным, хранящимся в WinFS, с помощью языка запросов Transact-Structured (T-SQL) и при необходимости получить данные в XML с помощью функции T-SQL FOR XML. API Win32 разрешает доступ к файлам и папкам, хранящимся в WinFS.
Для решения проблемы можно использовать несколько шаблонов доступа. Например, можно выполнить запрос T-SQL, который возвращает набор контактов в качестве управляемых объектов типа Contact WinFS. Независимо от используемого API, каждый API в конечном итоге управляет данными в хранилище WinFS с помощью T-SQL.
Во многих случаях вы предпочитаете использовать управляемый API WinFS. Эти классы платформа .NET Framework автоматически выполняют сопоставление связей объектов, необходимое для преобразования между объектно-ориентированными конструкциями программирования, и выполняют необходимый T-SQL для получения доступа к данным WinFS.
Использование управляемых классов WinFS
Управляемые классы WinFS находятся в System.Storage
пространстве имен и его вложенных пространствах имен. Многие приложения также будут использовать определения типов WinFS из System.Storage.Core
пространства имен. Кроме того, можно использовать типы из более специализированных пространств имен. Например, управляемые классы, которые управляют системным определением Contact, находятся в 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. Следующий код создает контекст элемента, подключенный к общей папке WinFS, идентифицируемой общим ресурсом \\machine\Legal Documents:
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 и добавим их в папку :
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 в указанном контексте элемента.
- Создает новую
FolderMember
связь с указанным именем, которая ссылается на person - Добавляет связь в
FolderMember
коллекциюPersonalContactsFolder
Relationship
Впоследствии я обножу DisplayName
свойства , GivenName
и Surname
элемента Person. Как всегда, я вызываю 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 определяет модель данных отношений, которая позволяет связывать элементы друг с другом. При определении схемы для типа данных можно определить ноль или более связей в рамках схемы. Например, схема Folder определяет связь FolderMember . Схема Организации определяет Employee
связь. Для каждой такой определенной связи существует класс, представляющий саму связь. Этот класс является производным Relationship
от класса и содержит члены, относящиеся к типу связи. Существует также строго типизированный "виртуальный" класс коллекции. Этот класс является производным от VirtualRelationshipCollection
и позволяет создавать и удалять экземпляры связи.
Связь связывает исходный элемент с целевым элементом. В предыдущем примере папка "Личные контакты" была исходным элементом, а элемент "Человек" — целевым элементом. Связь FolderMember
в основном указывает, что элемент Person относится к папке "Личные контакты" в качестве члена папки.
При определении связи вы определяете, сохраняет ли связь целевой элемент в существовании ( удержание) или не сохраняет ли целевой элемент ссылочной связью. При создании отношения удержания к целевому элементу WinFS увеличивает количество ссылок для целевого элемента. При удалении связей удержания WinFS уменьшает количество ссылок на целевой элемент. Элемент больше не существует в хранилище, когда его количество ссылок достигает нуля. WinFS никогда не изменяет количество ссылок целевого объекта при создании или уничтожении ссылочной связи с целевым объектом. Таким образом, целевой элемент может исчезнуть из хранилища, когда его количество ссылок достигает нуля, а связь может ссылаться на несуществующий элемент.
WinFS определяет связь FolderMember
как удержанную связь. Большинство других классов отношений являются ссылочными связями.
Элементы папки
Теперь, когда вы знаете о элементах ссылок, я могу уточнить свое описание элементов папки. Папка — это элемент WinFS с коллекцией элементов Link. Целевой объект каждого элемента 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. Вы указываете, какой тип элемента следует найти, и все специальные ограничения, которым должны соответствовать возвращаемые элементы. Кроме того, каждый класс элементов, Person
например , File
, Folder
и т. д., также содержит статические методы, позволяющие находить элементы этого типа.
Метод FindAll
возвращает один или несколько элементов, соответствующих указанным условиям. Метод ItemContext.FindAll
экземпляра требует указать тип искать элементы. Кроме того, при необходимости можно указать условия поиска, чтобы сузить область поиска. Например, следующий код находит все элементы Person со свойством DisplayName
, значение которого начинается с "Brent".
FindResult res = ctx.FindAll (typeof(Person), "DisplayName='Brent%'");
foreach (Person p in res) {
// Use the Person item somehow
}
Кроме того, можно использовать статический FindAll
Person
метод класса следующим образом:
FindResult res = Person.FindAll (ctx, "DisplayName='Brent%'");
foreach (Person p in res) {
// Use the Person item somehow
}
В обоих этих примерах метод всегда возвращает коллекцию элементов, FindAll
соответствующих типу и заданным условиям. Эта коллекция может не содержать элементов, но вы не получите пустую ссылку FindResult
для . Поэтому всегда выполняете итерацию по коллекции, чтобы получить найденные элементы.
Если вы знаете, что только один элемент будет соответствовать запрошенным типам и заданным условиям фильтра, можно использовать FindOne
метод . Однако будьте внимательны— FindOne
метод создает исключение, когда находит несколько элементов, соответствующих вашему запросу.
Person p = Person.FindOne (ctx, "DisplayName='Brent Rector'");
Второй строковый параметр — это выражение фильтра, позволяющее указать дополнительные ограничения, которым должны соответствовать возвращаемые элементы. Базовым форматом выражения фильтра является строка в формате "<propertyName> <operator> <propertyValue>
".
WinFS вызывает выражение выражением OPath
. Синтаксис аналогичен, хотя и не идентичен синтаксису выражений XPath
, используемым для идентификации элементов в XML-документе. Этот фрагмент кода возвращает все элементы файлов с расширением doc или txt:
FindResult Files = File.FindAll (ctx, "Extension='doc' || Extension='txt'");
Эти выражения могут быть довольно сложными. Например, в следующем заявлении возвращаются все элементы person, представляющие работников работодателя с DisplayName
основным преимуществом:
string pattern = "Source(EmployeeOf).DisplayName='Main Benefit'";
FindResult result = Person.FindAll (ctx, pattern);
Вот еще один. Я хочу, чтобы элементы Person, где фамилия не является "Ranier", а адреса электронной почты не заканчиваются на ".edu".
string filter = "PersonalNames[Surname!='Ranier'] &&
!(PersonalEmailAddresses[Address like '%.edu'])");
FindResult result = Person.FindAll (ctx, filter);
Определение определенного элемента
Часто требуется создавать ссылки на элементы в хранилище WinFS. В конечном итоге эти ссылки используются для поиска соответствующего элемента. Ранее в этой главе я показал, как использовать ссылку для ссылки на элемент. Ссылки используют понятное строковое удостоверение для ссылки, и это строковое имя должно быть уникальным в пределах папки, содержащей ссылку. Другими словами, для идентификации элемента, на который указывает ссылка, требуется папка и одна из содержащихся в ней ссылок.
Однако можно создать несколько ссылок с одинаковым понятным строковым именем, если добавить ссылки в разные папки, чтобы все имена в одной папке оставались уникальными. Обратите внимание, что эти несколько ссылок с одинаковым понятным текстовым именем фактически не должны ссылаться на один и тот же целевой элемент. Они могли, но они не должны.
В таких случаях поиск всех ссылок с определенным понятным текстовым именем (например, с помощью FindAll
) вернет несколько результатов. Затем необходимо проверить источник каждой ссылки, чтобы определить содержащую папку, а затем определить, какая ссылка ссылается на нужный элемент.
Нам нужен способ сослаться на любой произвольный элемент в магазине, например предположим, что мне нужен 3287-й элемент в магазине. К счастью, вы можете сделать именно это.
Поиск элемента по ItemID_Key значению
WinFS присваивает каждому вновь созданному элементу идентификационный номер на основе GUID, известный как его ItemID_Key
свойство. На практике значение, скорее всего, ItemID_Key
будет уникальным для всех томов WinFS, однако 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);
}
Общие функции
API WinFS предоставляет несколько функций для всего спектра классов данных. Эти функции:
- Асинхрония
- Transactions
- Уведомления
- Поддержка больших двоичных объектов и потоков
- Курсоры и разбиение по страницам
Асинхрония
API WinFS позволяет выполнять запросы асинхронно. API WinFS использует стандартные шаблоны асинхронной модели программирования .NET.
Transactions
Хранилище WinFS — это хранилище транзакций. Таким образом, WinFS позволяет выполнять транзакционные обновления в хранилище с помощью BeginTransaction
методов , CommitTransaction
и AbortTransaction
в объекте ItemContext
, как показано в следующем примере:
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 использует концепции краткосрочных и долгосрочных подписок. Краткосрочная подписка длится до тех пор, пока приложение не отменит подписку или не завершит работу приложения. Долгосрочная подписка сохраняется после перезапуска приложения. Наблюдатели API WinFS — это набор классов, которые позволяют приложениям получать выборочные уведомления об изменениях в хранилище WinFS и предоставлять сведения о состоянии, которые могут быть сохранены приложением для поддержки сценариев приостановки и возобновления.
Класс Watcher
может уведомлять приложение об изменениях в различных аспектах объектов WinFS, включая следующие:
- Изменения элементов
- Изменения внедренных элементов
- Изменения расширения элементов
- Изменения связей
Когда наблюдатель вызывает событие, он отправляет данные о состоянии наблюдателя с уведомлением о событии. Приложение может хранить эти данные состояния для последующего извлечения. Впоследствии эти данные состояния наблюдателя можно использовать, чтобы указать WinFS, что вы хотите получать события для всех изменений, произошедших после создания состояния.
Модель программирования наблюдателя также позволяет отключить любое сочетание добавленных, измененных и удаленных событий. Его также можно настроить для создания начального события, которое имитирует добавление всех существующих элементов, расширений элементов, связей и т. д.
Структура наблюдателя WinFS разбита на классы, описанные в следующей таблице.
Класс | Назначение или описание |
---|---|
WatcherOptions |
Класс для указания начальных параметров область и детализацииStoreWatcher |
StoreWatcher |
Класс квинтэссенциального просмотра элементов WinFS, внедренных элементов, расширений элементов и связей |
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-объектов и потоков
API-интерфейсы поддержки BLOB-объектов и потоков все еще находятся в потоке на момент написания этой статьи. Последние сведения о доступе к BLOB-объектам и потокам в хранилище WinFS см. в документации.
Курсоры и разбиение по страницам
Различные Find
методы в классах WinFS могут возвращать (потенциально) большую коллекцию объектов . Эта коллекция эквивалентна набору строк в мире баз данных. Традиционные приложения баз данных используют страничный курсор для эффективной навигации по большому набору строк. Этот курсор ссылается на одну строку (тонкийкурсор) или набор строк (курсор страницы). Идея заключается в том, что приложения извлекают строки на одной странице за раз; они также могут определить одну строку на странице для размещенного обновления и удаления. API WinFS предоставляет разработчикам аналогичные абстракции для работы с большими коллекциями.
По умолчанию операция поиска предоставляет динамический курсор только для чтения и прокрутки над возвращаемой коллекцией. Приложение может иметь курсор пожарного шланга для достижения максимальной производительности. Курсор пожарного шланга является курсором только вперед. Приложение может получить страницу строк за раз, но следующая операция извлечения начнется с последующим набором строк— ему не удастся вернуться назад и повторно получить строки. В каком-то смысле строки передаются из хранилища в приложение, как вода из пожарного шланга— отсюда и название.
Свойство CursorType
в FindParameters
классе позволит приложению выбирать между пожарным шлангом и прокручиваемым курсором. Для пожарных шлангов и прокручиваемых курсоров приложение может задать размер страницы с помощью PageSize
свойства FindParameters
класса . По умолчанию размер страницы равен 1.
Привязка данных
Классы данных WinFS можно использовать в качестве источников данных в среде привязки данных. Классы WinFS реализуют IDataEntity
интерфейсы (для отдельных объектов) и IDataCollection
(для коллекций). Интерфейс IDataEntity
предоставляет уведомления целевому объекту привязки данных об изменениях свойств в объекте источника данных. Интерфейс IDataCollection
позволяет определить базовый тип объекта в полиморфной коллекции. Он также позволяет получить System.Windows.Data.CollectionManager
объект , который перемещается по сущностям данных коллекции и предоставляет представление (например, порядок сортировки или фильтр) коллекции. Я подробно обсудим привязку данных в главе 5.
Безопасность
Модель безопасности WinFS в основном предоставляет набор Rights
для Principal
в следующими Item
способами:
- Безопасность задается на уровне
Items
. - Набор прав может быть предоставлен принципу безопасности в
Item
. Этот набор включает в себя: READ, WRITE, DELETE, EXECUTE (для всех элементов), CREATE_CHILD, ADMINISTER и AUDIT. (Дополнительные права предоставляются на элементы папки.) - Пользователи и приложения являются принципами безопасности. Права приложения заменяют права пользователя. Если у приложения нет разрешения на удаление контакта, пользователь не может удалить его с помощью приложения независимо от разрешений пользователя.
- Безопасность настраивается с помощью правил; каждое
Grant
правило является и применяется к тройной: (<ItemSet, PrincipalSet, RightSet>
). - Сами правила хранятся как
Items
.
Получение прав на элемент
Каждый класс элементов WinFS имеет метод с именем GetRightsForCurrentUser
, который возвращает набор прав (READ, WRITE, DELETE и т. д.), которые текущий пользователь имеет для указанного элемента. Кроме того, метод возвращает набор методов, которые WinFS позволяет выполнять пользователю.
Установка прав на элемент
WinFS использует специальный тип Элемента , SecurityRule
для хранения сведений о разрешениях для Items
. Таким образом, настройка и изменение прав ничем не отличаются от манипулирования любыми другими Item
в WinFS. Ниже приведен пример кода, показывающий, как задать права на элемент папки:
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();
}
Расширение API WinFS
Каждый встроенный класс WinFS содержит стандартные методы, такие как Find*
и имеет свойства для получения и задания значений полей. Эти классы и связанные с ними методы составляют основу API WinFS и позволяют узнать, как использовать один класс, и в целом знать, как использовать многие другие классы WinFS. Однако, хотя стандартное поведение полезно, для каждого конкретного типа данных требуется дополнительное поведение, зависят от конкретного типа.
Поведение домена
В дополнение к этим стандартным методам каждый тип WinFS обычно имеет набор методов, относящихся к предметной области, уникальных для этого типа. (На самом деле в документации По WinFS определения типов часто называются схемой, отражающей наследие базы данных WinFS.) WinFS называет эти методы для конкретных типов поведением предметной области. Например, ниже приведены некоторые варианты поведения домена в схеме контактов:
- Определение допустимости адреса электронной почты
- Получение коллекции всех элементов папки с заданной папкой
- Присвоение идентификатора элемента, получение объекта, представляющего этот элемент
- Человек, получающий его статус в сети
- Создание нового или временного контакта с вспомогательными функциями
Поведение Value-Added
Классы данных с поведением предметной области формируют основу, на которую опирались разработчики приложений. Однако классы данных не могут и не желают предоставлять все возможные действия, связанные с данными.
Вы можете предоставить новые классы, расширяющие базовые функциональные возможности, предоставляемые классами данных WinFS. Для этого нужно написать класс, методы которого принимают один или несколько классов данных WinFS в качестве параметров. В следующем примере и WindowsMessageServices
являются гипотетическими классами, OutlookMainServices
которые используют стандартные классы WinFS MailMessage
и 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");
Затем вы можете зарегистрировать эти пользовательские классы в WinFS. Данные регистрации будут связаны с метаданными схемы, которые WinFS поддерживает для каждого установленного типа WinFS. WinFS сохраняет метаданные схемы в виде элементов WinFS; Таким образом, вы можете обновлять, запрашивать и извлекать их так же, как и все остальные элементы WinFS.
Указание ограничений
Модель данных WinFS допускает ограничения значений для типов. WinFS оценивает и применяет эти ограничения при добавлении элементов в хранилище. Однако иногда требуется убедиться, что входные данные удовлетворяют ограничениям, не влечет за собой затраты на обход сервера. WinFS позволяет автору схемы или типа решить, поддерживает ли тип проверку ограничений на стороне клиента. Если тип поддерживает проверку на стороне клиента, тип будет иметь метод проверки, который можно вызвать, чтобы убедиться, что объект удовлетворяет указанным ограничениям. Обратите внимание, что независимо от того, вызывает Validate
ли разработчик метод, WinFS по-прежнему проверяет ограничения в хранилище.
Использование API WinFS и SQL
API WinFS позволяет разработчику получить доступ к хранилищу WinFS с помощью знакомых концепций среды CLR. В этой главе я использовал следующий шаблон кодирования для доступа к WinFS:
- Привязка к объекту
ItemContext
. - Найдите нужные элементы.
- Обновите элементы.
- Сохраните все изменения в хранилище.
Шаг 2 по сути является запросом к хранилищу. API WinFS использует синтаксис выражения фильтра на OPath
основе для указания этих запросов. Во многих случаях для большинства задач должно быть достаточно использовать выражения фильтра. Однако в некоторых случаях разработчику потребуется использовать все возможности и гибкость SQL.
В SQL присутствуют следующие возможности, но они недоступны при использовании выражения фильтра:
- Агрегирование (
Group By
,Having
,Rollup
) - Проекция (включая вычисляемые выражения выбора, distinct, IdentityCol, RowGuidCol)
- Для XML
- Union
- Параметр
- Правое/полное/перекрестное соединение
- Вложенные выделения
- Присоединение к таблице, отличной от WinFS
Поэтому важно, чтобы разработчик WinFS мог легко переходить между API SQLClient и API WinFS, используя один или другой в различных местах в коде.
Агрегирование и группирование с помощью SQL, а затем использование API WinFS
Владелец малого бизнеса, Джо, хочет определить, кто его первые 10 клиентов и отправить подарочные корзины к ним. Предположим, что клиент является типом элемента схемы. Это означает, что независимого поставщика программного обеспечения предоставил схему для типа клиента в WinFS, и, следовательно, это также означает, что хранилище WinFS теперь может содержать элементы клиента. Элемент Customer имеет удерживаемую ссылку на схематизированный тип элемента заказа. Элемент заказа имеет внедренную коллекцию заказов на линии следующим образом:
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, который впоследствии используется для выполнения SQL-запроса к хранилищу WinFS. Этот объект команды повторно использует соединение, используемое контекстом элемента. Строки 4–12 создают запрос, а строка 14 выполняет запрос. Запрос возвращает 10 основных клиентов следующим образом: инструкция SELECT в строках 6–12 создает сгруппированную таблицу, содержащую общую стоимость заказов каждого клиента; Предложение ORDER BY в строке 12 в сочетании с модификатором TOP 10 в строке 6 выбирает только первых 10 клиентов в этой сгруппированной таблице.
Класс GiftBasketOrder
является пользовательским классом, который использует объект API Customer
WinFS. Я создаю экземпляр в строке GiftBasketOrder
16.
Строка 19 использует SQLDataReader
для считывания первого столбца возвращенного набора строк и приводит его к объекту CustomerData
.
При определении нового типа в WinFS (известном как создание новой схемы) фактически определяются два типа: управляемый класс и постоянный формат этого класса в хранилище WinFS. WinFS всегда добавляет суффикс Data к имени класса, чтобы создать имя типа хранилища. Таким образом, например, при определении нового типа клиента, который находится в хранилище WinFS, WinFS создает параллельный CustomerData
определяемый пользователем тип (определяемый пользователем тип) WinFS.
Первый столбец набора строк содержит объект хранилища CustomerData
. Я передаю этот объект конструктору Customer
класса , и конструктор инициализирует новый объект из CustomerData
объекта . Этот пример является типичным для создания объектов API WinFS с помощью определяемых пользователем типов хранилища.
Строка 24 добавляет клиента в Recipients
коллекцию GiftBasketOrder
.
Наконец, я использую Send
метод в gbOrder, чтобы "отправить" этот заказ.
Навигация в API, а затем статистическая обработка в SQL
Предположим, вы хотите найти среднюю зарплату (за 10 лет) для генерального директора каждой компании в моем портфеле. Используйте следующие предположения:
- У меня есть папка с именем "Компании в моем портфеле", которая содержит элементы типа Organization.
-
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 открывается контекст для общей папки WinFS "Компании в моем портфеле". Строки 3–11 создают параметризованный SQL-запрос, который можно использовать в контексте папки. Этот запрос возвращает среднюю заработную плату для данного сотрудника (представленную параметром @LinkID
). Строки 10 и 11 указывают, что @LinkID
является параметром типа BigInt
. Я выполняю этот запрос позже в примере в строке 20.
Строка 13 получает Folder
объект , представляющий папку, указанную в общей папке, указанной при создании контекста. Строки 15 и 16 настраивают цикл для прохождения коллекции Organization
объектов в этой папке.
Для каждой организации строка 17 возвращает EmployeeData
объект для генерального директора.
Строка 19 подготавливает запрос и задает для параметра соответствующее значение LinkID, а затем в строке 20 выполняется параметризованный select.
Строка 21 считывает следующую и единственную строку из результата запроса, а в строках 22 и 23 выводится имя генерального директора и средняя зарплата за 10 лет.
Сводка
Хранилище данных WinFS предоставляет гораздо более обширную модель хранения данных, чем традиционные файловые системы. Так как он поддерживает данные, поведение и связи, сложно классифицировать WinFS как файловую систему, реляционную базу данных или объектную базу данных. Это немного всех этих технологий в одном продукте. WinFS предоставляет общее определение вездесущей информации, которая является глобально видимой и доступной для всех приложений, работающих на Longhorn. Приложения могут использовать возможности запросов, извлечения, обновления транзакций и фильтрации WinFS; Поэтому разработчик тратит меньше времени на разработку кода для доступа к данным и хранения, а также на работу с уникальными функциями приложения.