Проблема с Entity Framework 4, комплексными типами, StoredProcs и временными таблицами - PullRequest
7 голосов
/ 15 июня 2010

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

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

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

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

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

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 ]

7 голосов
/ 04 августа 2010

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

  1. Использовать Таблицы переменных вместо -> может быть, мастер импорта предпочитает это?
  2. Назовите ваши возвращаемые поля.

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

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

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

например ..

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

а затем ...

Добавьте этот сохраненный процесс в ваш дизайнер EF / мастер / и т. Д. ... Теперь правильные поля должны быть определены дизайнером.КЛАССНО.Да ... все значения жестко закодированы ... но это нормально (пока). Как только вы будете довольны, что EF теперь правильно обновлен, вернитесь в свой сохраненный процесс и удалите все жестко закодированные SELECT (что мы и сделалина вышеуказанном этапе).Теперь мы удалим комментарии, которые мы закомментировали весь реальный код.Таким образом, у вас должен быть исходный сохраненный процесс, обратно.

... и теперь EF обновлен и не знает, что мы изменили расположение вашего хранимого процесса.

win:)

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

1 голос
/ 16 марта 2011

Вот вариант отличного ответа Pure.Krome. Вместо того, чтобы комментировать ваш код sproc, создайте новое представление, которое состоит только из «поддельного» оператора select, описанного 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 ( подробности здесь ). Найдите спрок в браузере модели. Щелкните правой кнопкой мыши и выберите «Добавить функцию импорта ...». Под «Возвращает коллекцию» выберите Entities. Выберите объект просмотра и нажмите «ОК». Теперь, когда ваша хранимая процедура вызывается, она выводит результаты в вашу сущность представления.

MyProject.MyEntities myContext = new MyProject.MyEntities();
var myQuery = myContext.usp_FOO(myRecordID);
FooWrapperViewEntity myFooEntity = new FooWrapperViewEntity();
myFooEntity = myQuery.FirstOrDefault();
0 голосов
/ 28 мая 2013

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

Подробнее см.

...