Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Технологии программирования / источники / ++часть 1 Совр веб-техн / 10. +Проект БД и работа с ними Веб-прилож.DOC
Скачиваний:
220
Добавлен:
10.05.2015
Размер:
845.82 Кб
Скачать

10.1.3. Ado.Net Entity Framework

ADO.NET Entity Framework (EF) – объектно-ориентированная технология доступа к данным, является object-relational mapping (ORM) решением для .NET Framework от Microsoft [9]. Предоставляет возможность взаимодействия с объектами как посредством LINQ в виде LINQ to Entities, так и с использованием Entity SQL. Для облегчения построения Веб-решений используется как ADO.NET Data Services, так и связка из Windows Communication Foundation и Windows Presentation Foundation, позволяющая строить многоуровневые приложения, реализуя один из шаблонов проектирования MVC, MVP или MVVM.

Платформа ADO.NET Entity Framework позволяет разработчикам создавать приложения для доступа к данным, работающие с концептуальной моделью приложения, а не напрямую с реляционной схемой хранения. Ее целью является уменьшение объема кода и усилий по обслуживанию приложений, ориентированных на обработку данных. Приложения Entity Framework дают следующие преимущества [10].

  1. приложения могут работать концептуальной моделью в терминах предметной области – в том числе с наследуемыми типами, сложными элементами и связями;

  2. приложения освобождаются от жестких зависимостей от конкретного ядра СУБД или схемы хранения;

  3. сопоставления между концептуальной моделью и схемой, специфичной для конкретного хранилища, могут меняться без изменения кода приложения;

  4. разработчики имеют возможность работать с согласованной моделью объектов приложения, которая может быть сопоставлена с различными схемами хранения, которые, возможно, реализованы в различных системах управления данными;

  5. несколько концептуальных моделей могут быть сопоставлены с единой схемой хранения;

  6. поддержка интегрированных в язык запросов (LINQ) обеспечивает во время компиляции проверку синтаксиса запроса относительно концептуальной модели.

10.1.3.1. Компоненты Entity Framework

Платформа Entity Framework представляет собой набор технологий ADO.NET, обеспечивающих разработку приложений, связанных с обработкой данных [10]. Архитекторам и разработчикам приложений, ориентированных на обработку данных, приходится учитывать необходимость достижения двух совершенно различных целей. Они должны моделировать сущности, связи и логику решаемых бизнес-задач, а также работать с ядрами СУБД, используемыми для сохранения и получения данных. Данные могут распределяться по нескольким системам хранения данных, в каждой из которых применяются свои протоколы, но даже в приложениях, работающих с одной системой хранения данных, необходимо поддерживать баланс между требованиями системы хранения данных и требованиями написания эффективного и удобного для обслуживания кода приложения.

В Entity Framework разработчики получают возможность работать с данными, представленными в форме относящихся к конкретным доменам объектов и свойств, таких как клиенты и их адреса, не будучи вынужденными обращаться к базовым таблицам и столбцам базы данных, где хранятся эти данные. Такая возможность появляется благодаря переходу на более высокий уровень абстракции, на котором разработчики могут работать с данными, применяя меньший объем кода для создания и сопровождения приложений, ориентированных на работу с данными.

Платформа Entity Framework является компонентом .NET Framework, поэтому приложения Entity Framework можно запускать на любом компьютере, на котором установлен .NET Framework 3.5 с пакетом обновления 1 (SP1).

10.1.3.1.1. Применение концептуальных моделей на практике

Давно известный и широко применяемый принцип проектирования в моделировании данных состоит в разделении модели данных на следующие три части: концептуальная модель, логическая модель и физическая модель. Концептуальная модель определяет сущности и связи в моделируемой системе. Логическая модель для реляционной базы данных обеспечивает нормализацию сущностей и связей в целях создания таблиц с ограничениями внешнего ключа. В физической модели учитываются возможности конкретной системы обработки данных путем определения зависящих от ядра базы данных подробных сведений о хранении данных, которые касаются секционирования и индексирование.

Физическая модель совершенствуется администраторами базы данных в целях повышения производительности, но программисты, которые разрабатывают код приложения, в основном вынуждены ограничиваться работой с логической моделью, подготавливая SQL-запросы и вызывая хранимые процедуры. Концептуальные модели в основном используются как инструмент для представления и обмена мнениями по поводу требований к приложению, поэтому чаще всего служат в качестве почти неизменных схем, которые рассматриваются и обсуждаются на ранних стадиях проекта, после чего перестают быть предметом внимания.

Платформа Entity Framework придает значимость концептуальным моделям, позволяя разработчикам выполнять запросы к сущностям и связям в концептуальной модели; при этом для перевода этих операций в команды, зависящие от источника данных, применяется сама платформа Entity Framework. Это позволяет отказаться от применения в приложениях жестко заданных зависимостей от конкретного источника данных. Концептуальная модель, модель хранения и их сопоставление выражаются во внешней спецификации, известной также как модель Entity Data Model (EDM). Модель хранения и сопоставление могут изменяться по мере необходимости, не требуя изменений в концептуальной модели, классах данных и коде приложения. Модели хранения зависят от поставщика, поэтому можно работать с согласованной концептуальной моделью через различные источники данных.

Модель EDM определяется следующими тремя файлами модели и сопоставления, которые имеют соответствующие расширения имен файлов.

  • Файл на языке CSDL (с расширением CSDL) определяет концептуальную модель.

  • Файл на языке SSDL (с расширением SSDL). Определяет модель хранения данных, которая называется также логической моделью.

  • Файл на языке MSL (с расширением MSL) определяет сопоставление модели хранения и концептуальной модели.

В Entity Framework эти файлы модели и сопоставления на основе XML используются для преобразования операций создания, чтения, обновления и удаления, выполняемых над сущностями и связями концептуальной модели, в эквивалентные операции в источнике данных (рис. 10.12). Модель EDM поддерживает даже сопоставление сущностей в концептуальной модели с хранимыми процедурами в источнике данных.

Рис. 10.12. Разработка сущностной модели данных

В модели EDM сущности и их связи моделируются с использованием двух основных типов.

  • EntityType: абстрактная спецификация подробных сведений о структуре данных в домене приложения.

  • AssociationType: логическое соединение между типами.

Схема проектирования модели EDM определяет структуру, семантику, ограничения и связи сущностей в домене приложения. В реализации служб объектов модели EDM концептуальная схема сопоставляется с EDM-схемой, которая содержит метаданные, описывающие модель хранения (обычно это таблицы в базе данных). Концептуальная схема используется для формирования классов программируемой модели объектов, которая применяется в коде приложения. Концептуальная схема и схема хранения используются также в технологии Entity Framework для проверки, выполнения запросов и обновления данных приложения во время выполнения.

10.1.3.1.2. Сопоставление объектов и данных

При использовании объектно-ориентированного программирования для взаимодействия с системами хранения данных возникают сложности. Безусловно, организация классов часто напоминает организацию таблиц реляционной базы данных, но такое соответствие не идеально. Несколько нормализованных таблиц часто соответствуют единственному классу, а связи между классами представлены иначе, чем связи между таблицами.

В существующих решениях была предпринята попытка устранить этот разрыв, часто называемый "несоответствием типов данных" (impedance mismatch), путем сопоставления с реляционными таблицами и столбцами только объектно-ориентированных классов и свойств. Вместо данного традиционного подхода в Entity Framework реляционные таблицы, столбцы и ограничения внешнего ключа логических моделей преобразуются в сущности и связи концептуальных моделей. Это позволяет достичь большей гибкости при определении объектов и оптимизации логической модели. С помощью инструментов Entity Data Model формируются расширяемые классы данных, основанные на концептуальной модели. Эти классы являются разделяемыми классами, которые могут быть расширены с помощью дополнительных членов, добавленных разработчиком. Классы, сформированные для определенной концептуальной модели, являются производными от базовых классов, предоставляющих службы объектов для материализации сущностей в виде объектов, а также для отслеживания и сохранения из менений. Разработчики могут использовать эти три класса для работы с сущностями и связями как с объектами, связанными свойствами навигации.

10.1.3.1.3. Компоненты платформы Entity Framework

Следующие функции и компоненты платформы Entity Framework работают совместно для обеспечения сквозной среды программирования.

  • Модель Entity Data Model (EDM) служит центром приложения Entity Framework. Она задает схему проекта, которая используется для построения программируемых классов, используемых кодом приложения.

  • Компонент Object Services позволяет программистам работать с классами CLR, созданными из концептуальной модели. Он также обеспечивает инфраструктурную поддержку для приложения Entity Framework, предоставляя такие службы, как управление состоянием, отслеживание изменений, разрешение идентификаторов, загрузка и переход по связям, распространение изменений объектов в модификации базы данных, а также поддержку запросов для Entity SQL.

  • Компонент LINQ to Entities обеспечивает поддержку LINQ при запросах к сущностям. Компонент LINQ to Entities позволяет разработчикам писать запросы к базе данных на одном из поддерживаемых языков программирования .NET Framework, например Visual Basic или Visual C#.

  • Язык Entity SQL подобен языку SQL и не зависит от типа хранилища. Он предназначен для создания запросов к сложным графам объектов, основанных на модели EDM, а также для управления ими.

  • Поставщик EntityClient расширяет модель поставщика ADO.NET путем доступа к данным в терминах сущностей и связей концептуальной модели. Он выполняет запросы, которые используют язык Entity SQL. Entity SQL предоставляет базовый язык запросов, который позволяет поставщику EntityClient связываться с базой данных.

  • Компонент метаданных ADO.NET управляет метаданными для всей платформы Entity Framework как во время разработки, так и во время выполнения. Все метаданные, связанные с моделями и сопоставлениями, доступны через интерфейсы метаданных, которые не зависят от механизма, используемого для хранения метаданных. Текущий механизм хранения использует файлы, которые основаны на трех диалектах XML: языке CSDL, языке SSDL и языке MSL.

  • Приложение Entity Framework включает изменяющийся набор средств, которые создают сопоставления и разделяемые классы, представляющие сущности концептуальной модели.

  • Приложение Entity Framework включает обновленный поставщик данных SqlClient, который поддерживает канонические деревья команд.

На рис. 10.13 показаны связи различных доступных пользователям интерфейсов программирования в приложении Entity Framework [10, 11]. Стрелка вниз обозначает запрос к источнику данных, а стрелка вверх – возвращаемые данные. Службы объектов создают каноническое дерево команд, которое представляет работу LINQ to Entities или Entity SQL с концептуальной моделью. Поставщик EntityClient преобразует это каноническое дерево команд, основанное на модели EDM, в новое каноническое дерево команд, содержащее эквивалентные операции для источника данных.

Рис. 10.13. Компоненты Entity Framework

10.1.3.1.4. Средства работы с моделью EDM

Наряду со средой выполнения Entity Framework, .NET Framework 3.5 с пакетом обновления 1 включает генератор моделей EDM (EdmGen.exe). Программа командной строки соединяется с источником данных и формирует модель EDM на основе сопоставления типа "один к одному" между сущностями и таблицами. В этой программе используется также файл концептуальной модели (с расширением CSDL) для формирования файла уровня объектов, содержащего классы, которые представляют типы сущностей и контекст ObjectContext.

Visual Studio 2008 включает в себя обширный набор поддерживаемых инструментов для создания и обслуживания модели EDM в приложении Visual Studio. Конструктор Entity Data Model поддерживает создание усовершенствованных сценариев сопоставления (таких как наследование типа "одна таблица на тип" и "одна таблица на иерархию"), а также разделение сущностей, которые сопоставлены с несколькими таблицами.

10.1.3.2. Создание сущностной модели данных

Для примера создания EDM будет использоваться база данных Northwind.

C помощью мастера EDM, который предоставляет список объектов, которые возможно смоделировать (рис. 10.14), включим все таблицы в модель, тем самым произведя взаимно-однозначное сопоставление таблиц сущностям [12].

Рис. 10.14. Мастер EDM

Источник: Обзор ADO.NET Entity Framework [12]

Помимо создания файлов CSDL, SSDL и MSL для всех таблиц в Northwind, мастер также создаст набор классов, основываясь на CSDL, представляющий модель. Часть этих классов показана на рис. 10.15 в окне Class View.

Мастер EDM отследил связь между таблицами Customers и Orders в базе данных и создал соответствующую ассоциацию в концептуальной модели. Поэтому класс Customers содержит свойство перемещения Orders, позволяющее разработчикам переходить от экземпляра класса Customers к любому из экземпляров класса Orders для него.

Рис. 10.15. Классы

Источник: Обзор ADO.NET Entity Framework [12]

10.1.3.3. Разбор CSDL

Метаданные, содержащиеся в CSDL-файле, содержат списки сущностей, представленных элементами EntityType, и связей, представленных элементами Association, относящихся к типу AssociationType. Далее показан фрагмент CSDL-файла, определяющий EntityType:

<EntityType Name="Customers" Key="CustomerID">

<Property Name="CustomerID" Type="String" Nullable="false"

MaxLength="4000" FixedLength="true" />

<Property Name="CompanyName" Type="String" Nullable="false"

MaxLength="4000" />

<Property Name="ContactName" Type="String" MaxLength="4000" />

<Property Name="ContactTitle" Type="String" MaxLength="4000" />

<Property Name="Address" Type="String" MaxLength="4000" />

<Property Name="City" Type="String" MaxLength="4000" />

<Property Name="Region" Type="String" MaxLength="4000" />

<Property Name="PostalCode" Type="String" MaxLength="4000" />

<Property Name="Country" Type="String" MaxLength="4000" />

<Property Name="Phone" Type="String" MaxLength="4000" />

<Property Name="Fax" Type="String" MaxLength="4000" />

<NavigationProperty Name="Orders"

Relationship="NorthwindModel.FK_Orders_Customers"

FromRole="Customers" ToRole="Orders" />

</EntityType>

Сущности содержат списки скалярных свойств, определяющих их. Атрибут Key показывает, какие свойства являются ключевыми. Составные ключи выделяются разделением имен свойств пробелами. Сущности также могут содержать специальные свойства, называемые NavigationProperty. Они определяют переходы от одной сущности к другой через ассоциации.

В следующем фрагменте CSDL определятся AssociationType между Customer и относящимися к нему Orders:

<Association Name="FK_Orders_Customers">

<End Role="Customers" Type=

"NorthwindModel.Customers"

Multiplicity="0..1" />

<End Role="Orders" Type=

"NorthwindModel.Orders" Multiplicity="*" />

</Association>

Элементы End в AssociationType указывают участвующих в ассоциации. В этом примере сущность Customers ассоциирована с сущностью Orders. Также сущность Customers может быть связана с любым числом сущностей Orders, что определяется атрибутом Multiplicity.

В то время как элементы EntityType и AssociationType определяют типы сущностей области и отношения между ними, элементы EntitySet и AssociationSet определяют их области применения. Все "наборы", которые должны быть сгруппированы вместе, содержатся внутри элемента EntityContainer.

Следующий фрагмент CSDL демонстрирует EntityContainer и часть его содержимого:

<EntityContainer Name="NorthwindEntities">

<EntitySet Name="Customers"

EntityType="NorthwindModel.Customers" />

<EntitySet Name="Orders"

EntityType="NorthwindModel.Orders" />

<AssociationSet Name="FK_Orders_Customers"

Association="NorthwindModel.FK_Orders_Customers">

<End Role="Customers" EntitySet="Customers" />

<End Role="Orders" EntitySet="Orders" />

</AssociationSet>

</EntityContainer>

Этот фрагмент включает наборы EntitySet для типов EntityType Customers и Orders: Здесь же объявляется ассоциация AssociationSet FK_Orders_Customers. Таким образом, этот фрагмент определяет сущности Customers и Orders, а также связь между ними.

10.1.3.4. Сопоставление хранилищу

Файл SSDL определяет структуру реляционных данных в базе данных. В нем также используются элементы XML EntityType и AssociationType, в этом случае для объявления структур таблиц и существующих в базе данных внешних ключей соответственно. Пространство имен файла SSDL основано на имени базы данных, использованной в EDM, тогда как элемент EntityContainer назван в соответствии со схемой базы данных. EntityContainer содержит наборы элементов EntitySet и AssociationSet, которые объявляют экземпляры таблиц и отношений, представленных элементами EntityType и AssociationType. Каждому набору EntitySet в файле SSDL соответствует таблица в базе данных.

Если EDM создается на основе базы данных, то файлы CSDL и SSDL достаточно похожи. Это потому, что модели созданы прямо из базы данных, и концептуальная модель сопоставляется логическому хранилищу напрямую. Файл MSL содержит прямое соответствие CSDL и SSDL. Все запросы на основе такой EDM транслируются в созданные команды SQL. Entity Framework также поддерживает использование хранимых процедур вместо создания запросов SQL.

Для сопоставления модели (CSDL) хранилищу (SSDL) используется элемент EntityContainerMapping. Атрибут StorageEntityContainer показывает название контейнера EntityContainer в хранилище, а атрибут EdmEntityContainer показывает соответствующий EntityContainer в модели. Для сопоставления набора EntitySet модели набору EntitySet хранилища требуется элемент EntitySetMapping. Атрибут Name определяет название набора EntitySet модели, а атрибут TableName определяет название соответствующего набора EntitySet в хранилище. Каждое свойство модели сопоставляется хранилищу посредством элемента ScalarProperty. Пример файла MSL:

<cs:EntitySetMapping cs:Name="Products">

<cs:EntityTypeMapping cs:TypeName="NorthwindModel.Products">

<cs:TableMappingFragment cs:TableName="Products">

<cs:ScalarProperty cs:Name="ProductID" cs:ColumnName="ProductID" />

<cs:ScalarProperty cs:Name="ProductName"

cs:ColumnName="ProductName" />

<cs:ScalarProperty cs:Name="QuantityPerUnit"

cs:ColumnName="QuantityPerUnit" />

<cs:ScalarProperty cs:Name="UnitPrice" cs:ColumnName="UnitPrice" />

<cs:ScalarProperty cs:Name="UnitsInStock"

cs:ColumnName="UnitsInStock" />

<cs:ScalarProperty cs:Name="UnitsOnOrder"

cs:ColumnName="UnitsOnOrder" />

<cs:ScalarProperty cs:Name="ReorderLevel"

cs:ColumnName="ReorderLevel" />

<cs:ScalarProperty cs:Name="Discontinued"

cs:ColumnName="Discontinued" />

<cs:Condition cs:ColumnName="Discontinued" cs:Value="0"/>

</cs:TableMappingFragment>

</cs:EntityTypeMapping>

</cs:EntitySetMapping>

10.1.3.5. Определение наследования

EDM также поддерживает модели, не соответствующие базе данных взаимно-однозначно. Например, используя базу данных Northwind, можно создать класс, например, называющийся DiscontinuedProducts, который наследует все свойства класса Products, но содержит только продукты, значение поля Discontinued для которых равно 1. Это упрощенная схема наследования, но она показывает, как применить наследование в EDM.

Первым шагом по созданию класса DiscontinuedProducts в концептуальной модели является открытие файла CSDL, создание нового типа EntityType, называющегося DiscontinuedProducts, и установка его атрибута BaseType в значение NorthwindModel.Products (схема и название базового EntityType). Порожденный тип EntityType наследует свойства EntityType Products, включая ключи. Дополнительный код CSDL для всего описанного выглядит так:

<EntityType Name="DiscontinuedProducts" BaseType="NorthwindModel.Products"/>

Следующим шагом в этом процессе является открытие файла MSL и удаление атрибутов TypeName и TableName элемента EntitySetMapping Products. Теперь они будут устанавливаться отдельно для каждого конкретного типа EntityType. Затем необходимо создать дочерний элемент EntityTypeMapping и установить TypeName как NorthwindModel.Products. Для каждого EntityType, порожденного от базового EntityType, EntitySetMapping должен включать элемент EntityTypeMapping. Далее нужно создать дочерний элемент EntityTypeMapping, называющийся TableMappingFragment, и установить для его атрибута TableName значение Products. В целом, эти шаги переносят сопоставление с элемента EntitySetMapping на более низкий и детальный уровень.

Далее необходимо закомментировать сопоставление свойства Discontinued и добавить элемент Condition, указывающий, что включены будут только записи со значением поля Discontinued, равным 0. После этого нужно скопировать целиком XML фрагмент EntityTypeMapping, поменять значение атрибута Name на DiscontinuedProducts и поменять значение в условии на 1.

Далее показан фрагмент файла MSL, в котором происходит сопоставление унаследованной сущности:

<cs:EntitySetMapping cs:Name="Products">

<cs:EntityTypeMapping cs:TypeName="NorthwindModel.Products">

<cs:TableMappingFragment cs:TableName="Products">

<cs:ScalarProperty cs:Name="ProductID" cs:ColumnName="ProductID" />

<cs:ScalarProperty cs:Name="ProductName"

cs:ColumnName="ProductName" />

<cs:ScalarProperty cs:Name="QuantityPerUnit"

cs:ColumnName="QuantityPerUnit" />

<cs:ScalarProperty cs:Name="UnitPrice" cs:ColumnName="UnitPrice" />

<cs:ScalarProperty cs:Name="UnitsInStock"

cs:ColumnName="UnitsInStock" />

<cs:ScalarProperty cs:Name="UnitsOnOrder"

cs:ColumnName="UnitsOnOrder" />

<cs:ScalarProperty cs:Name="ReorderLevel"

cs:ColumnName="ReorderLevel" />

<!--<cs:ScalarProperty cs:Name="Discontinued"

cs:ColumnName="Discontinued" />-->

<cs:Condition cs:ColumnName="Discontinued" cs:Value="0"/>

</cs:TableMappingFragment>

</cs:EntityTypeMapping>

<!--</cs:EntitySetMapping>

<cs:EntitySetMapping cs:Name="DiscontinuedProducts">-->

<cs:EntityTypeMapping cs:TypeName=

"NorthwindModel.DiscontinuedProducts">

<cs:TableMappingFragment cs:TableName="Products">

<cs:ScalarProperty cs:Name="ProductID" cs:ColumnName="ProductID" />

<cs:ScalarProperty cs:Name="ProductName"

cs:ColumnName="ProductName" />

<cs:ScalarProperty cs:Name="QuantityPerUnit"

cs:ColumnName="QuantityPerUnit" />

<cs:ScalarProperty cs:Name="UnitPrice" cs:ColumnName="UnitPrice" />

<cs:ScalarProperty cs:Name="UnitsInStock"

cs:ColumnName="UnitsInStock" />

<cs:ScalarProperty cs:Name="UnitsOnOrder"

cs:ColumnName="UnitsOnOrder" />

<cs:ScalarProperty cs:Name="ReorderLevel"

cs:ColumnName="ReorderLevel" />

<cs:Condition cs:ColumnName="Discontinued" cs:Value="1"/>

</cs:TableMappingFragment>

</cs:EntityTypeMapping>

</cs:EntitySetMapping>

10.1.3.6. Сопоставление нескольким таблицам

Другим способом уйти в EDM от строгого взаимно-однозначного сопоставления модели хранилищу является сопоставление одной сущности в модели нескольким таблицам в хранилище. Между таблицами Contacts и ContactNameSplit в базе данных Northwind есть взаимно-однозначная связь, и можно объединить их в одну сущность в модели. Для примера создадим в модели сущность, включающую все поля таблицы Contacts и поля Title и Name из таблицы ContactNameSplit.

Первым изменением является добавление двух дополнительных свойств в элементе EntityType Contacts в файле CSDL: Name и Title. Эти два новых свойства в модели теперь должны быть сопоставлены хранилищу в файле MSL. Необходимо изменить элемент EntitySetMapping для EntitySet Contacts, чтобы представлять сопоставление нескольким таблицам, например, удалив атрибуты TableName и TypeName. Эти атрибуты объявляются в элементе EntitySetMapping, только если набор EntitySet в модели взаимно-однозначно сопоставлен набору EntitySet в хранилище.

Поскольку сопоставление набора EntitySet модели набору EntitySet хранилища для Contacts было удалено, необходимо создать ему замену. Такой заменой является дочерний элемент EntityTypeMapping. Их необходимо создать два – по одному для представления каждой из таблиц Contacts и ContactNameSplit в хранилище. Элементы EntityTypeMapping определяют атрибут TypeName для каждого из наборов EntitySet.

Внутри каждого из элементов EntityTypeMapping помещен дочерний элемент, называющийся TableMappingFragment. Этот элемент включает атрибут TableName, соответствующий набору EntitySet в хранилище. В TableMappingFragment определены все элементы ScalarProperty, сопоставляющие свойства модели хранилищу. Далее показан обновленный элемент EntitySetMapping Contacts, который теперь сопоставляет таблицы Contacts и ContactSplitName хранилища одному набору EntitySet модели:

<cs:EntitySetMapping cs:Name="Contacts">

<cs:EntityTypeMapping cs:TypeName="NorthwindModel.Contacts">

<cs:TableMappingFragment cs:TableName="Contacts">

<cs:ScalarProperty cs:Name="ContactID"

cs:ColumnName="ContactID" />

<cs:ScalarProperty cs:Name="ContactType"

cs:ColumnName="ContactType" />

<cs:ScalarProperty cs:Name="CompanyName"

cs:ColumnName="CompanyName" />

<cs:ScalarProperty cs:Name="ContactName"

cs:ColumnName="ContactName" />

<cs:ScalarProperty cs:Name="ContactTitle"

cs:ColumnName="ContactTitle" />

<cs:ScalarProperty cs:Name="Address" cs:ColumnName="Address" />

<cs:ScalarProperty cs:Name="City" cs:ColumnName="City" />

<cs:ScalarProperty cs:Name="Region" cs:ColumnName="Region" />

<cs:ScalarProperty cs:Name="PostalCode"

cs:ColumnName="PostalCode" />

<cs:ScalarProperty cs:Name="Country" cs:ColumnName="Country" />

<cs:ScalarProperty cs:Name="Phone" cs:ColumnName="Phone" />

<cs:ScalarProperty cs:Name="Extension"

cs:ColumnName="Extension" />

<cs:ScalarProperty cs:Name="Fax" cs:ColumnName="Fax" />

<cs:ScalarProperty cs:Name="PhotoPath"

cs:ColumnName="PhotoPath" />

</cs:TableMappingFragment>

</cs:EntityTypeMapping>

<cs:EntityTypeMapping cs:TypeName="ContactNameSplit">

<cs:TableMappingFragment cs:TableName="ContactNameSplit">

<cs:ScalarProperty cs:Name="ContactID" cs:ColumnName="ID" />

<cs:ScalarProperty cs:Name="Name" cs:ColumnName="Name" />

<cs:ScalarProperty cs:Name="Title" cs:ColumnName="Title" />

</cs:TableMappingFragment>

</cs:EntityTypeMapping>

10.1.3.7. Использование EntityClient

Доступ к концептуальной модели Entity Framework может быть организован тремя способами: EntityClient, Object Services, LINQ to Entities

Рассмотрим первый их них.

EntityClient абстрагирован от логического хранилища, поскольку он взаимодействует с концептуальной моделью посредством своего собственного текстового языка, называющегося Entity SQL. Все запросы Entity SQL, выполняемые через EntityClient, компилируются в деревья команд, посылаемые в хранилище. Преобразование запросов Entity SQL через концептуальную модель и далее в хранилище обеспечивается Entity Framework.

Классы EntityClient похожи на классы распространенных поставщиков ADO.NET. Например, запросы EntityClient выполняются в объекте EntityCommand, которому необходим объект EntityConnection для подключения к EDM. Хотя EntityClient взаимодействует с сущностями EDM, он не возвращает экземпляры сущностей, а вместо этого возвращает все результаты в виде объекта DbDataReader. При помощи DbDataReader EntityClient может возвращать стандартный набор строк и столбцов, либо представление более сложной иерархии данных.

На следующем примере показано использование EntityClient для подключения к концептуальной модели и получения списка заказчиков из Москвы:

string city = "Москва";

using (EntityConnection cn = new EntityConnection("Name=NorthwindEntities"))

{

cn.Open();

EntityCommand cmd = cn.CreateCommand();

cmd.CommandText =

"SELECT VALUE c FROM NorthwindEntities.Customers " +

"AS c WHERE c.City = @city";

cmd.Parameters.AddWithValue("city", city);

DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);

while (rdr.Read())

Console.WriteLine(rdr["CompanyName"].ToString());

rdr.Close();

}

EntityConnection может воспринимать полную строку подключения к концептуальному слою или ее название в файле App.Config. Строка подключения содержит перечень файлов метаданных (файлов CSDL, MSL и SSDL), а также строку подключения к хранилищу, зависящую от конкретной базы данных:

"metadata=.\NorthwindEntities.csdl|.\NorthwindEntities.ssdl|.\NorthwindEntities.msl;provider=System.Data.SqlClient;

provider connection string='

Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;

Integrated Security=True; User Instance=True'"

Код в примере показывает, как создать объект EntityConnection и выполнить для него команду EntityCommand. Запрос, написанный на Entity SQL, обращается к набору EntitySet Customers в EDM.

10.1.3.8. Использование служб Object Services

Другим способом взаимодействия с данными, представленными EDM, является использование служб Object Services. Службы Object Services предоставляют возможность загружать объекты и следовать любым связям, определенным в EDM. Службы Object Services используют EntityClient для получения данных. Службы Object Services добавляют разрешение идентификаторов, что при использовании DataSet приходится делать вручную. Они также обеспечивают неизменность объектов и отслеживание изменений через события, чтобы позволять явные загрузку и сохранение. За счет этого снижается число обращений к серверу.

Службы Object Services позволяют возвращать списки объектов напрямую – можно возвращать как проекции, так и определенные сущности. Например, пользуясь Object Services, можно получить List<Customers>, как определено в EDM. Объекты Customers можно просмотреть, изменить значения, а затем сохранить данные в базе данных.

При использовании проекций при помощи служб Object Services возвращаемые данные не будут обновляемым объектом. Поскольку проекции возвращают конкретные свойства сущностей, а не сущности целиком, службы Object Services не могут сохранить изменения в спроецированных данных обратно в базу данных. Если необходимо обновить данные, лучшим вариантом будет возвращать сущность целиком и не использовать проекцию.

Можно использовать службы Object Services для выполнения запросов Entity SQL или можно писать запросы, используя LINQ to Entities. Следующий пример демонстрирует запрос на Entity SQL, выполняемый через службы Object Services для получения списка заказчиков:

string city = "Москва";

ObjectQuery<Customers> query = northwindContext.CreateQuery<Customers>(

"SELECT VALUE c FROM Customers AS c WHERE c.City = @city",

new ObjectParameter("city", city));

foreach (Customers c in query) Console.WriteLine(c.CompanyName);

В EDM EntityContainer представлен классом, производным от ObjectContext (в этом примере northwindContext). Класс ObjectContext реализует интерфейс ObjectQuery<T>, позволяя создавать запросы, используя Entity SQL и LINQ.

Метод CreateQuery принимает параметризованный оператор Entity SQL, определяющей запрос, возвращающий список сущностей Customers. Собственно выражение SQL, обращающееся к базе, выполняется при итерации по ObjectQuery<Customers> оператором foreach.