Главная Другое
Экономика Финансы Маркетинг Астрономия География Туризм Биология История Информатика Культура Математика Физика Философия Химия Банк Право Военное дело Бухгалтерия Журналистика Спорт Психология Литература Музыка Медицина |
страница 1 САНКТ-ПЕРЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Математико-механический факультет Кафедра системного программирования
Дипломная работа студента 545 группы Бешко Михаила Юрьевича Научный руководитель ………….. А. Н. Иванов к. ф.-м. н. / подпись / Рецензент ………….. Д. В. Луцив ст. преп. / подпись /
«Допустить к защите» Заведующий кафедрой, д. ф.-м. н., профессор ………….. А. Н. Терехов / подпись / Санкт-Петербург 2008
Постановка задачи 6 Основная часть 7 Основные понятия в области ИС, ориентированных на данные 7 Обзор Silverlight 8 Обзор LINQ 12 Преимущества и недостатки выбранных технологий 15 Организация архитектуры UI типового приложения.
Доступ к данным. 19 Классы FilteringEntity и механизм фильтрации при помощи Expression 21 Выводы 24 Результаты работы 25 Список использованной литературы 26 Введение Развитие компьютерных технологий неуклонно продолжается. Предприятия самых разных размеров и направлений деятельности всё более и более активно используют IT-решения для выполнения своих далеко не только компьютерных задач. При этом предпосылки могут быть самые разные, например: желание автоматизировать некоторый бизнес-процесс, сделать более удобным, наглядным, быстрым (а то и всё вместе) выполнение каких-либо операций, систематизировать базу знаний или данных о производственных ресурсах. Список можно продолжать бесконечно. Теперь рассмотрим интересующий нас сегмент рынка программного обеспечения. Среди множества разнообразных систем можно выделить класс приложений, которые особенно актуальны и востребованы на сегодняшний день – это приложения, ориентированные на интенсивную работу с данными (Data-Intensive Information Systems). Вариантом решения в таком случае является архитектура «клиент-сервер», причем клиент – это настольное приложение, а сервер – это сервер баз данных, который обрабатывает запросы клиента. Настольные приложения подняли планку качества от уровня неэргономичных решений до действительно больших высот в смысле функциональности, технических возможностей, удобства и интерактивности работы с пользователем. Но мир не стоит на месте – всё более и более критичной стала возможность удалённой работы с центральным сервером. Простой пример: топ-менеджер проводит большое время в командировках, но хочет при этом не терять доступ к системе управления ресурсами своего предприятия. В таком случае появляется понятие трёхзвенной архитектуры и варианты решения, когда есть полнофункциональное настольное приложение и плюс к нему простой web-клиент, либо даже только настольное приложение, но которое работает не напрямую с базой, а через web-сервис (3е звено). Тем временем web-технологии бурно развиваются. Ранее web-сайты предоставляли пользователю лишь возможность просмотра статической информации, в последние же годы web-приложения всё ближе и ближе достигают по уровню возможностей настольные системы. В качестве технологических прорывов и «историй успеха» можно привести широко известные GMail, Google Maps, Google Suggest, социальные сети (особенно развившиеся в 2007 году, вспомним хотя бы армию клонов Facebook). Решались самые разные проблемы: уход от статического содержимого к динамическому, придание приложениям легковесности, интерактивность работы с пользователем, открытость стандартов, представление информации как сервиса. С недавнего времени технологии web-разработки особенно бурно развиваются в сторону создания визуально и функционально богатых web-приложений (Rich Internet Applications – RIA). Крупнейшие компании-разработчики выпустили набор схожих продуктов, предназначенных для создания RIA. Назовём основных игроков этого рынка: Microsoft, Sun (JavaFX), Ruby on Rails, Adobe (Flash, Flex, ColdFusion). ![]() (Рис.1 Web 2.0 превращается в Enterprise 2.0) Взгляд на возможности этих технологий наводит на мысль, что уже сейчас разработчики могут создавать web-приложения, приближающиеся к настольным по функциональным возможностям, внешнему виду и интерактивности работы с пользователем. Утверждается, что, грамотно выбрав технологии и разработав архитектуру, можно создать решение, состоящее из web-клиента, сервера приложений и сервера баз данных, которое будет удовлетворять современным функциональным, интерфейсным и эргономическим требованиям.
Таким образом, естественным путём развития описанных идей является разработка средства создания интерактивных web-приложений, ориентированных на данные с использованием в полную силу современных web-технологий и шаблонов проектирования. Постановка задачиЗадачей работы является апробация актуального среза технологий Microsoft – тройки Silverlight, LINQ, WCF – при разработке каркаса создания web-приложений, ориентированных на интенсивную обработку данных (data oriented web-application framework). Имеем такую приблизительную схему типовой системы: ![]()
Вернёмся к постановке задачи. Она разделяется на следующие подзадачи:
При этом общая функциональность должна быть вынесена в библиотеки, которые будут использоваться приложениями во время выполнения. Кроме того, архитектура должна предусматривать внесение изменений в генерируемый код.
В рамках этой задачи предполагается рассмотреть различные варианты генерации, выбрать оптимальный, и сделать строгое описание соответствующих алгоритмов. Сама задача реализации генераторов будет решена позже, когда Silverlight 2 перейдёт из состояния beta-тестирования в RTM.
Основная частьОсновные понятия в области ИС, ориентированных на данныеНе будем глубоко вдаваться в теорию моделирования, а, в частности, теорию моделирования интерфейса, скажем лишь, что можно выделить 2 уровня модели UI [1]:
Макромодель интерфейса REAL-IT в настоящий момент содержит три типа форм [1]:
Список Список предоставляет пользователю возможность работать с множеством объектов одного класса, а также выбирать объект для выполнения над ними каких-либо действий. Каждый элемент списка соответствует одному объекту основного класса, однако при его отображении может использоваться информация о других объектах модели данных. Список может предоставлять пользователю следующие возможности:
Карточка Карточка предназначена для просмотра и редактирования информации об отдельном объекте. К такой информации относятся значения атрибутов объекта, а также информация о его связях с другими объектами. Карточка может предоставлять пользователю следующие возможности:
Карточка также может содержать встроенные списки. Форма-отношение Форма-отношение представляет интерфейс для отношения «многие ко многим». Вариант организации интерфейса для такого отношения, помимо формы, – это встроенный в карточку список с функциями «Добавить», «Убрать», взамен традиционных для отношения один-ко-многим «Создать», «Редактировать», «Удалить». Естественным образом функция «Добавить» добавляет в таблицу-отношение запись, а «Убрать» удаляет выбранную, при этом обе операции не затрагивают сущности связываемых таблиц, только сами связки. Обзор SilverlightSilverlight – это кросс-платформенный, кросс-браузерный плагин, который позволяет web-приложениям, созданным для него, работать на компьютерах, на которых установлен один из поддерживаемых Интернет браузеров (на данный момент это – IE 7,8, Mozilla Firefox 1.5, 2.0, Safari). Поддерживаемые платформы – это Windows, MacOS и, в самое ближайшее время, Linux. Основной фокус первых версий Silverlight (1.0-1.1) – это поддержка работы с медиа ресурсами в web-приложениях: проигрывание видео, звука, продвинутая работа с графикой. Теоретически, их можно было бы использовать для создания богатых бизнес приложений, но практически это не поддерживалось стандартной библиотекой, которая тогда состояла из графических примитивов (многоугольник, эллипс и т.п.), но не содержала традиционных элементов управления. Разработчики обосновывали это тем, что основная работа велась над back-end модулями Silverlight и обещали вскоре удовлетворить запросы разработчиков. С выходом версии Silverlight 2.0 beta1 (поскольку на данный момент она последняя, то здесь и далее будем писать просто «Silverlight 2») ситуация улучшилась, стандартная библиотека обогатилась привычным набором элементов управления: Button, Calendar, CheckBox, DataGrid, DatePicker, GridSplitter, HyperlinkButton, ListBox, RadioButton, ScrollViewer, Slider, ToolTip, WatermarkedTextBox, а значит можно утверждать, что технология Silverlight стала подходить в качестве основы для создания RIA. Перечислим кратко основные особенности Silverlight 2:
Стандартными инструментами разработки Silverlight-приложений на данный момент являются Microsoft Visual Studio 2008 и Microsoft Expression Blend. Это – следствие тенденции разделить работу дизайнера и программиста. Blend является средой, специализированной на создании именно дизайна приложений. Поддерживается Drag-and-drop, редактирование цветовых свойств в стиле программ для работы с графикой, создание и редактирование timeline’ов (изменение состояния объектов во времени). Но работа с кодом в нём реализована на простейшем уровне. В Visual Studio же есть нормальная поддержка intellisense, отладки и прочих стандартных возможностей. На момент написания работы была ограниченная поддержка редактирования интерфейса из Visual Studio (можно править декларативный код, и изменения отображаются в дизайнере интерфейса, но drag and drop отсутствовал. Silverlight приложение содержит обязательный элемент – класс, унаследованный от Application, который будет являться точкой входа приложения. Экземпляр этого класса обеспечивает контроль во время выполнения, управление ресурсами на уровне приложения и обработку необработанных ошибок. Другими важными структурными элементами Silverlight-проекта являются обычные пользовательские классы и пользовательские элементы управления (контролы), унаследованные от класса UserControl. Таким образом «страниц» и «форм» в Silverlight нет, а, значит, единицей взаимодействия на уровне UI для нас будут именно элементы управления. В обычном случае контрол состоит из файла описания интерфейса в формате XAML и файла на одном из поддерживаемых процедурных языков программирования (C#, VB.NET), содержащего пользовательский код (codebehind). XAML – это основанный на XML формат описания интерфейсов в Silverlight и WPF (Windows Presentation Foundation, большой настольный прародитель Silverlight). Элементы XAML-разметки представляют собой экземпляры объектов CLR, а атрибуты – поля и события этих элементов. Пример простого XAML-файла разметки: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> В этом файле объявлен корневой элемент Grid, позволяющий укладывать элементы управления в табличном формате. Внутри него элементы стандартной библиотеки TextBlock и DatePicker, текстовая надпись и поле с возможностью выбора даты. «x:Name» – это атрибут, значение которого определяет имя, по которому можно будет обращаться к данному контролу из .NET кода. То есть из парного к MyControl.xaml файла MyControl.xaml.cs мы сможем обратиться к этому элементу как к полю класса MyControl по имени dateCreation. Silverlight-проект компилируется в набор обычных .NET сборок, которые затем упаковываются в .xap-файл (ZIP архив, по сути). Далее полученный Silverlight-объект может быть помещён на статическую HTML страницу в виде элемента В качестве выводов можно сказать, что использование Silverlight оправдано при повышенных требованиях к дизайну GUI разрабатываемого приложения или, когда требуется большая интерактивность либо идёт упор на работу с media-содержимым. К примеру: для media-библиотеки, системы электронных географических карт, Интернет-банка Silverlight будет отличной технологией создания GUI. Также Silverlight удобно использовать, если нужно web-приложение с действительно сложным GUI в плане взаимного расположения элементов управления, либо если эти элементы управления будут меняться, трансформироваться, перемещаться. Для подобных вещей в Silverlight и в интегрированной среде разработки Expression Blend есть соответствующие специализированные инструменты. Обзор LINQLINQ (.NET Language Intergrated Query) – это набор нововведений .NET Framework 3.5, которые в комплексе дают возможность писать SQL-like запросы (не обязательно к реляционной базе, можно даже просто к IEnumerable коллекциям), естественным образом интегрированные в код. Речь идёт о таких вещах как:
1. 2. и 3. вместе дают возможность на выходе в запросах получать массив / элемент данных произвольного типа (имеющего произвольный набор полей). Например: выбирая данные из таблицы, берём в массив результатов подмножество полей таблицы-источника: var myAnonymColl = from e in db.Employees //where some_predicate select new { NewIdField = e.Id, NewNameField = e.Name} .ToList(); При исполнении этого запроса к таблице Employees базы данных мы получим список объектов анонимного типа, который будет сконструирован во время компиляции. Этот тип будет снабжён двумя автоматическими “get; set;” свойствами NewIdField и NewNameField, по которым можно будет получать доступ к соответствующим полям. А тип массива myAnonymColl статически определится на этапе компиляции. Ключевое слово «var» отнюдь не обозначает переход к динамической типизации. Это – просто синтаксический сахар, элемент языка, придуманный для удобства именно в таких ситуациях, когда тип возвращаемого выражения не имеет удобочитаемого представления.
Теперь поддержаны синтаксисом C# 3.0. С точки зрения типа являются делегатами с соответствующей сигнатурой. Применяются в частности для фильтрации. Func //Где Func public delegate TResult Func //используем: bool res = myLambda(7, “Michael”);
Все основные LINQ-методы, дающие желанную гибкость и мощность работы с коллекциями и таблицами ,в частности, оформлены в виде extension методов. Например, вот объявление extension-метода Where из метаданных библиотеки System.Linq: public static IQueryable this IQueryable Expression Такое объявление значит, что в области видимости пространства имён System.Linq для объектов классов, реализующих интерфейс* IQueryable IQueryable<Employee> myQuery = from e in db.Employees select e; List Причем, extension методы объявлены и реализованы в одном классе System.Linq.Queryable, а использоваться могут как методы экземпляров всех подходящих по интерфейсу классов. *Интерфейс IQueryable – это IEnumerable над некоторым источником данных.
Есть такое понятие, как LINQ-provider, то есть компонент, поддерживающий доступ к некоторому виду ресурсов в LINQ стиле. В частности в стандартной библиотеке .NET Framework 3.5 есть компонент доступа к базам данных Microsoft SQL Server, который называется LINQ to SQL. Он включает в себя инструмент автоматического объектно-реляционного моделирования таблиц БД в терминах .NET классов. С этими классами затем можно работать как с таблицами базы: проводить стандартные select insert update delete операции. LINQ запросы при компиляции интерпретируются в вызовы стандартных .NET методов (Where, GroupBy, Join, OrderBy, Sum, Union etc.), а при исполнении – в SQL-запросы в случае LINQ to SQL. Это следует учитывать при использовании лямбда-выражений для фильтрации – слишком сложное лямбда-выражение может не иметь интерпретации в SQL. Важно понимать, что большая часть LINQ запросов выполняется отложено (deferred execution), т.е. объявленный запрос будет исполнен только тогда, когда будут явно использованы или перечислены оператором foreach его результаты, если не произведен явно вызов одного из методов ToList, ToEnumerable, ToArray. Полезное для работы следствие: отложенное выполнение позволяет в несколько этапов добавлять фильтры к объявленному запросу. И ещё одно неочевидное свойство LINQ to SQL запросов: ленивая загрузка (lazy loading). Это понятие обозначает то, что объекты, на которые есть ссылки в некоторых сущностях подгружаются только тогда, когда к ним идёт явное обращение. Приведём пример: у класса Employee есть ссылка на фирму, на которой работает сотрудник: class Employee { // много-много полей Public Firm EmployeeFirm; // ещё много полей } Изначально ссылка EmployeeFirm нулевая, но при обращении, например, к полю фирмы в запросе: from e in db.Employees where e.EmployeeFirm.Name = “Lanit-Tercom” select e; механизм LINQ to SQL определяет, что нужно подгрузить соответствующую сущность типа Firm. Причем, мы можем управлять ленивой загрузкой явно: указать в рамках серии операций с базой, что нужно подгружать для сущности A связанные с ней сущности B.
Преимущества и недостатки выбранных технологийИтак, мы получили видение в первом приближении того, что собой представляет Silverlight. Рассмотрим теперь те аспекты его возможностей, которые реально помогут при решении целевой задачи, преимущества такого решения, выпишем обнаруженные недостатки, неудобства (разобрав их на те, которые накладывает сама технологическая платформа и те, которые производители обязуются разрешить в ближайших релизах), а также сравним полученный вариант реализации слоя представления (View) с другими доступными вариантами решения. Вернёмся к постановке задачи. Конечная цель – получить каркас для создания визуально и функционально богатых web-приложений. В случае настольных приложений возможности построения интерактивных бизнес-приложений обеспечиваются отработанной годами системой окон, элементов управления, событий. При этом приложение может представлять из себя MDI-контейнер, т.е. быть хранилищем дочерних окон, что даёт большую гибкость взаимодействий и организации архитектуры. Кроме того, некоторые платформы обеспечивают возможность наследования форм, что тоже можно было бы умело использовать. Так, например, в REAL-IT.NET, где технологической основой была библиотека Windows Forms из стандартного набора .NET Framework, частные формы (и карточки, и списки) наследовались от общих, которые заключали в себе основную функциональность. Но при этом базовые формы содержали некоторый набор общих элементов управления. К примеру, типовым шагом было отнаследоваться от класса общей карточки, открыть частную форму-наследник в дизайнере форм Visual Studio и заняться настройкой её внешнего вида – добавить дополнительные функциональные кнопки (помимо основных, уже имеющихся: «Ок», «Отмена» и т.п.), текстовые поля, надписи и прочее. Причем, результаты работы дизайнера базовой формы и дочерней дополняли друг друга естественным образом. Поработав с панелью общих кнопок базовой формы, можно было перейти к редактированию наследной и настроить её рабочую область, не трогая ту же базовую панель, но при этом видя её и имея возможность редактировать её свойства по необходимости. Это обеспечивало качественный уровень переиспользования кода и возможность по умолчанию задать общий вид всех типовых форм приложения (через настройку базовой карточки, базового списка и других). Одной из серьёзных проблем Silverlight 2, унаследованной от WPF, является то, что декларативная сущность XAML не предназначена для наследования одних XAML-контролов от других. То есть мы можем создать класс, наследный от существующего контрола, добавить дополнительную логику или создать новые элементы управления вручную. Но дизайнера форм мы лишены при таком наследовании, а, значит, теряется одна из главных идей подхода – возможность редактирования дизайна и базовой «формы», и наследной с отображением изменений. В базовой правится остов, в наследных – частные детали представления (поля и т.п.). В этом смысле Silverlight пока проигрывает и Windows Forms, и ASP.NET (с его MasterPages). Но вернёмся к решению этой проблемы позже, когда вспомним о возможности использования архитектурного шаблона Control-as-View. Ещё одним, хотя и менее существенным недостатком является то, что в стандартном наборе элементов управления Silverlight нет класса комбо-бокса (Combo-box, Drop-down list или как-угодно ещё) – поля с возможностью выбора элемента из выпадающего списка. Это решается просто. В данной работе использован контрол DropDown из свободно распространяемой сторонней библиотеки Liquid. Есть подозрение, что в ближайшем релизе Silverlight комбо-боксы появятся, поэтому считаем решение временным. Такой акцент именно на комбо-бокс сделан по простой причине: этот элемент управления имеет очень широкое применение в UI информационных систем, ориентированных на данные. С его помощью представляются поля карточек, соответствующие колонкам-связям, когда в самом поле объекта модели, о карточке которого идёт речь, хранится ссылка на ключ, а в выпадающем списке выбираем из значений (например, имён), «подтянутых» из таблицы, на которую идёт ссылка. Также стоит ещё раз подчеркнуть, что стандартная библиотека классов Silverlight является лишь подмножеством .NET Framework 3.5. В частности, вообще не доступно пространство имён System.Data. Напомним, что в нём находятся такие важные и часто используемые при работе с базами данных классы, как DataRow, DataTable etc., а, следовательно, придётся отказаться от довольно старой, но проверенной временем парадигмы организации взаимодействия с моделью при помощи не типизированных сущностей типа DataRow. Такая парадигма практически не даёт возможности для статического контроля типов, но зато в некотором смысле имеет большую гибкость: доступ к конкретным полям идёт просто по строковому имени, динамически, поэтому операция взятия значения в колонке строки данных не требует ни рефлексии, ни «знания» того, с какой конкретно сущностью модели имеем дело. Это – своего рода слабая связность между бизнес-логикой и структурой модели. Silverlight предоставляет широкие возможности для организации взаимного расположения элементов управления, в нём есть взятая из WPF система Layout management. Поддерживается вложенность. Можно в обычной таблице с данными (DataGrid) помимо стандартных текстовых колонок использовать шаблонные колонки (TemplateColumn), причем внутренностью каждой ячейки в таком случае может стать произвольно организованная система элементов управления. Как пример использования, таблица/список хранимых объектов медиа-библиотеки. В текстовых колонках показываем информацию (название, дату модификации), а в последней колонке – мини-проигрыватель, медиа-данные для которого логикой подтягиваются из файлового сервера по пути, взятому из БД-таблицы. Организация архитектуры UI типового приложения.
|
HTTP метод |
CRUD операция |
Описание |
POST |
CREATE |
Создать новый элемент |
GET |
RETRIEVE |
Получить существующий |
PUT |
UPDATE |
Изменить |
DELETE |
DELETE |
Удалить |
У Microsoft есть свежая технология, реализующая такую парадигму. Она называется ADO.NET Data Services (старое кодовое имя Project Astoria) [9]. Не будем вдаваться в детали, информация о проекте общедоступна. Подчеркнём лишь основные его особенности, который могут оказаться полезны:
Благодаря так организованным сервисам можно получить функциональный интерфейс для простых операций, когда сами по себе действия достаточно примитивны и атомарны, но могут затрагивать сущности, сколь угодно глубоко вложенные и связанные, а также какие угодно поля сущностей.
Однако, в целевой области – информационных системах, ориентированных на данные, нередко встречаются операции большей сложности, чем реализуемые таким способом. Например, множественные соединения таблиц с вложенными запросами, группировками, не атомарные операции, в т.ч. организованные в транзакции, и т.д. и т.п. Ограничение накладывает только степень сложности схемы базы. Ясно, что для таких операций понадобится другой механизм. Идеально подходят «классические» веб-сервисы: объявлен контракт операции, а метод, выполняющий эту операцию на сервере, может быть произвольной сложности. Технология, реализующая последний подход, нам уже не так важна, поэтому просто будем использовать самую последнюю актуальную и поддерживаемую Silverlight-приложениями – WCF.
Таким образом, изящным и функциональным решением выглядит пара REST + SOA (см. [10]), когда REST-сервис покрывает большинство простых запросов – получить список всех сущностей A, добавить новую сущность B, изменить существующую C, а WCF-операции обслужат всю составную логику.
Проблема в том, что на данный момент технология ADO.NET Data Services не поддерживает работу с приложениями Silverlight 2 beta1, хотя Microsoft обещает в beta2 обеспечить эту поддержку. Поэтому пока придётся обойтись WCF-сервисами и придумать механизм организации интерфейса Operation Contract’ов, который даст необходимый уровень гибкости. Задача создания такого механизма была решена в рамках данной работы и ниже следует описание этого решения с обоснованием его деталей и особенностей.
Рассмотрим такой архитектурный блок, как Список – это список объектов модели определённого типа с возможностью фильтрации, поиска, сортировки. Следовательно, data-сервис должен иметь интерфейс выдачи сущностей разных типов с разными видами фильтрации:
GetEmployees, GetFirms, GetCountries, etc.
С учётом возможности использовать LINQ можно было бы держать на сервере по одному методу для каждого списка / таблицы, а фильтрующую функцию передавать в виде лямбда-выражения.
Например, на сервере объявляем метод, который будет доступен клиенту:
List
Вызываем его на клиенте:
myGrid.DataSource = svc.GetEmployees(myLambdaExpr);
Где myLambdaExpr – это лямбда-выражение, предикат фильтрации, например:
e => e.Firm_Id == 69
(только сотрудники, работающие на фирме с идентификатором «69»)
Рефлексию также нельзя использовать (можно было бы передавать объект типа MethodInfo из свойства System.Delegate.Method нашей функции Func
Остаются следующие варианты:
В данной работе реализован последний механизм.
Был сгенерирован класс:
[DataContract()]
public partial class Employee : INotifyPropertyChanging, INotifyPropertyChanged
{
private int _Id;
private System.Nullable
private EntityRef
[Column(Storage="_Id", DbType="Int NOT NULL", IsPrimaryKey=true)]
[DataMember(Order=1)]
public int Id
{ ... }
[Column(Storage="_Name", DbType="NVarChar(50)")]
[DataMember(Order=2)]
public string Name
{ ... }
[Column(Storage="_Firm_Id", DbType="Int")]
[DataMember(Order=3)]
public System.Nullable
{ ... }
[Association(Name="Firm_Employee", Storage="_Firm", ThisKey="Firm_Id", IsForeignKey=true)]
[DataMember]
public Firm Firm
{ ... }
}
На месте троеточий не интересующий нас очевидный код.
полю int Id будет соответствовать пара:
IQueryable
query = query.Where(emp => MyMethodWithProperSignature(emp));
то вызов абстрактного метода MyMethodWithProperSignature не сможет быть интерпретирован в SQL, даже если там безобидный код, проверяющий поле Employee на равенство с константной. Поэтому нам нужно использовать структурированные выражения. Но должная гибкость обеспечивается выбранным подходом. Так, например, реализован механизм который «подцепляет» к существующему дереву новый переход по связи. Например, известно дерево выражений: B -> C -> bool. (У сущности типа B перейти по ссылке на сущность типа C и применить уже к ней фильтрующий предикат). Если мы фильтруем на самом деле сущность типа A, но по полю косвенно связанной с ней сущности типа C то достаточно подцепить новую веточку к дереву, чтоб получить A -> B -> C -> bool. Пример из реального приложения для этих абстрактных выкладок: нужно выбрать тех сотрудников, чьи фирмы расквартированы в стране с именем «Россия». Ручной код выглядел бы так:
employeeQuery.Where(e = > e.Firm.Country.Name == “Россия”);
Благодаря тому, что в генерируемых фильтрующих классах ссылкам на связанные сущности классов модели соответствуют ссылки на соответствующие фильтрующие сущности, получаем возможность цепной фильтрации при сохранении относительно слабой связности data-сервиса с клиентом. Причем в приведенном примере необходимо инициализировать в фильтрующем объекте одно нужное фильтрующее поле – код на сервере достаточно умён, чтоб самостоятельно построить и добавить к запросу нужную ветку выражений.
К примеру, пусть наш серверный класс web-сервиса носит имя DataService и лежит в файле DataService.cs. Понятие partial классов позволяет разнести его методы по нескольким файлам: DataService.Employee.cs, DataService.Firm.cs
Соответственно, в той части, что соответствует работе с объектами Employee модели, например, будут следующие сгенерированные методы:
List
string UpdateEmployee(Employee modifiedEntity, Employee originalEntity)
string DeleteEmployee(Employee entityToDelete)
Одним из основных результатов работы является разработанная архитектура типовых приложений. Она достаточно простая, но вместе с тем легко расширяемая и гибкая. При разработке этой архитектуры были учтены особенности выбранных технологий и решены многие из появившихся проблем.
Уход от абстрактных кортежей с динамическим набором колонок привел к необходимости генерировать базовый интерфейс операций data-сервиса для каждого типа объектов взамен использования общего абстрактного механизма.
Применение LINQ на стороне сервера позволило реализовать простой, но эффективный paging-механизм.
Передача клиентских запросов на web-сервис, а, следовательно, сериализация параметров, заставила отказаться от возможности фильтрации при помощи лямбда-выражений (поскольку последние являются делегатами, а, значит, не сериализуемы). Взамен была придумана концепция фильтрующих сущностей, которые на стороне сервера интерпретируются в выражения, принимаемые LINQ.
Поскольку клиент физически удалён от сервера и к тому же является web-приложением, то все операции взаимодействия с data-сервисом пришлось сделать асинхронными, а в случаях, когда таких операций несколько и они связаны, нужно было обеспечить их синхронизацию.
Отсутствие в Silverlight наследования для классов с XAML-описанием интерфейса лишило возможности выносить общие элементы управления в родительские формы. Отчасти это было решено архитектурно (удачным выбором шаблона проектирования, аккуратной его адаптацией и реализацией), а отчасти смещением части логики с библиотек поддержки на генератор REAL-IT.
Практическими результатами работы являются: