Статьи

Отображение результатов хранимой процедуры в пользовательский объект в Entity Framework

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

Сопоставить хранимые процедуры с пользовательским объектом

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

Как сделать взлом?

В следующем примере я буду использовать следующую хранимую процедуру :

CREATE PROCEDURE dbo.GetCourseIDAndCredits
AS
BEGIN
    SET NOCOUNT ON 
    SELECT CourseID, Credits
    FROM Course
END

Обратите внимание, что эта хранимая процедура проста и показывает, как выполнить сопоставление с пользовательским объектом. Хранимая процедура возвращает идентификатор курса со своими кредитами.

Шаг 1
Импортируйте хранимую процедуру в модель хранилища с помощью Entity Framework Wizard .

Шаг 2
Создайте сущность CourseCredits, которая соответствует столбцам, которые возвращает хранимая процедура . Сделайте свойство CourseID первичным ключом сущности. На следующем рисунке показан результат шага 2:

Шаг 3
Используйте функцию импорта функций дизайнера и в диалоговом окне « Добавление импорта функций » установите тип возвращаемого значения хранимой процедуры для нашей новой сущности CourseCredits (если вы не знакомы с «Импортом функций», вы можете прочитать мой предыдущий пост на эту тему). На следующем рисунке показано диалоговое окно:

Шаг 4
Создайте тип сущности в SSDL, который будет определением типа сущности, который мы собираемся сопоставить с сущностью CourseCredits. Откройте модель в редакторе Xml и определите тип сущности CourseCredits, например:

<EntityType Name="CourseCredits">   <Key>    <PropertyRef Name="CourseID" />  </Key>   <Property Name="CourseID" Type="int" Nullable="false"/>   <Property Name="Credits" Type="int"/></EntityType>

Шаг 5
Поскольку Entity Framework ограничивает нас отображением каждой сущности в таблицу или представление, нам нужно использовать хак и создать DefiningQuery для SSDL . Определите сущность CourseCredits, установленную следующим образом в SSDL :

<EntitySet Name="CourseCreditsSet" EntityType="SchoolModel.Store.CourseCredits">  <DefiningQuery>    SELECT cast(0 as int)  CourseID, cast(0 as int) Credits    WHERE 1 = 2  </DefiningQuery></EntitySet> 

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

Шаг 6

Сопоставьте сущность CourseCredits в конструкторе с созданным фиктивным DefiningQuery в представлении сведений о сопоставлении :

Шаг 7
Проверьте решение. Следующий тестовый код выведет на выход сопоставленные объекты:

using (SchoolEntities context = new SchoolEntities()){    var courses = context.GetCourseIDAndCredits();    foreach (var course in courses)    {        Console.WriteLine("{0} {1}", course.CourseID, course.Credits);    }    Console.ReadLine();} 

И результат выполнения кода:

Резюме

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