Проблема с Entity Framework 4, сложными типами, хранимыми примерами и временными таблицами

Я закрываю колени на Entity Framework 4 и сталкиваюсь с небольшой проблемой.

У меня есть несколько хранимых процедур, которые я втягиваю в свой EDMX. Когда я создаю сложные типы из этих процессов, EF не имеет проблем с получением информации о столбцах. За исключением одного места. Некоторое время озадачиваясь, я выяснял, что моя временная таблица заполняется, что вызывает проблему. На самом деле это просто вызов INSERT в таблицу temp, которая вызывает проблему. Я на самом деле не заполняю его никакой информацией.

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

Ниже приведен пример proc, который не работает. Запустите это в БД и добавьте proc к вам EDMX. Затем попробуйте получить информацию о столбцах на экране "Добавить функцию импорта". Ничего не возвращается. Прокомментируйте INSERT в таблице temp и получите информацию о столбце, и она работает.

Спасибо, Стив

CREATE PROCEDURE dbo.TestProc
AS
SET NOCOUNT ON 
 CREATE TABLE #TempTable(
 StartDate datetime
 )
 INSERT INTO #TempTable
 SELECT null
 DROP TABLE #TempTable
 SELECT 1 AS ReturnValue
SET NOCOUNT OFF
GO
3 ответа

Несколько вещей, чтобы попробовать.

  • Используйте Таблицы переменных вместо этого → возможно, мастер импорта предпочитает это?
  • Назовите свои поля возврата.

Попробуйте использовать следующие хранимые процедуры (непроверенные.. просто задумываясь вслух...)

CREATE PROCEDURE dbo.Foo
AS
 SET NOCOUNT ON
 DECLARE @ResultTable TABLE (SomeId INTEGER)
 INSERT INTO @ResultTable
 SELECT DISTINCT Id AS Identity -- Or u can rename this field to anything...
 FROM SomeExistingTableWhichHasAnIdentityField
GO

Попробуйте и посмотрите, обновляется ли мастер сейчас.

-

Попытка # 2:)

Хорошо, когда разработчик/мастер EF/независимо от того, что не удается выяснить ТОЧНО, что мой сохраненный процесс, вероятно, будет возвращен, я обычно делаю следующее: -

  • Убедитесь, что хранимая процедура вообще не существует в дизайне/контексте EF и т.д. (у вас есть чистая отправная точка)
  • Откройте свою хранимую процедуру и /* /* закомментируйте ВСЕ ПОСЛЕ определения процедуры.

например..

ALTER PROCEDURE dbo.Foo
(
 Bar1 INT,
 Bar2 TINYINT,
 ... // whatever u have as your optional input arguments //
)
AS
 SET NOCOUNT ON
 /* 
 .... every thing in here is commented out 
 */
GO

Теперь... 3. Добавьте принудительный поддельный возврат в сохраненный процесс, который (более или менее) просто определяет структуру/поля вывода.

например..

ALTER PROCEDURE dbo.Foo
(
 Bar1 INT,
 Bar2 TINYINT,
 ... // whatever u have as your optional input arguments //
)
AS
 SET NOCOUNT ON
 SELECT 1 AS Id, 1 AS UserId, 1 AS SomeOtherId, 
 CAST('AAA' AS NVARCHAR(350)) AS Name,
 -- etc etc etc..
 /* 
 .... every thing in here is commented out 
 */
GO

а затем...

  1. Добавьте этот хранимый процесс в ваш EF-конструктор/мастер/etc... Теперь правильные поля должны быть "определены" дизайнером. ЗДОРОВО. Да.. значения все жестко запрограммированы.. но это нормально (до сих пор).
  2. После того, как вы счастливы, что EF теперь обновлен правильно, вернитесь к сохраненному процессу и удалите все hardcoded SELECT (что мы сделали на предыдущем шаге). Теперь мы удаляем комментарии, которые мы прокомментировали весь настоящий код. Таким образом, вы должны иметь свой оригинальный хранимый proc, назад.

... и теперь EF обновляется и не знает, что мы изменили сантехнику вашего сохраненного proc.

win:)

это работает для ya?


Вот вариант отличного ответа Pure.Krome. Вместо того, чтобы комментировать ваш sproc-код, создайте новое представление, которое состоит только из "поддельного" выбора, описанного Pure. Представление будет использоваться для создания объекта. Затем объект вида становится контейнером для результатов хранимой процедуры.

Create View dbo.FooWrapperView as 
 Select IsNull(MyPrimaryID,-999) as IntFieldName, --IsNull disallows nulls so EF designer will make this the primary key.
 NullIf(CAST('AAA' as VarChar(20)), '') as VarChar20FieldName, --NullIf allows null so EF designer will NOT make this part of the primary key.
 NullIf(CAST('AAA' as VarChar(42)), '') as VarChar42FieldName,
 NullIf(CAST(1.1 as DECIMAL(8, 5)), '') as Decimal85FieldName

В дизайнере объектов щелкните правой кнопкой мыши и выберите "Обновить модель из базы данных", затем выберите представление оболочки (и sproc, если вы еще этого не сделали). Это создаст объект, сопоставленный с видом фальшивой оболочки. Дизайнер выбирает первичный ключ на основе представлений IsNull и NullIf (здесь). Найдите sproc в браузере модели. Щелкните его правой кнопкой мыши и выберите "Добавить функцию импорта...". В разделе "Возвращает коллекцию" выберите "Объекты". Выберите объект просмотра и нажмите "ОК". Теперь, когда вы вызываете свою хранимую процедуру, она выгружает результаты в вашу сущность вида.

MyProject.********** myContext = new MyProject.**********();
var myQuery = myContext.usp_FOO(myRecordID);
FooWrapperViewEntity *********** = new FooWrapperViewEntity();
*********** = myQuery.FirstOrDefault();


Сначала вам нужно создать обычную процедуру хранения, не используя временную таблицу. эта процедура хранения будет содержать все имя столбца (обычная таблица + временная таблица). Теперь вы сможете создать сложный тип в вашем EDMX

Подробнее об этом

licensed under cc by-sa 3.0 with attribution.