В этом посте я собираюсь объяснить, как отобразить результаты хранимой процедуры на созданный пользователем объект, который мы создали с помощью дизайнера 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 это будет решено.