EF4 - выбранная хранимая процедура не возвращает столбцы - PullRequest
60 голосов
/ 20 августа 2011

У меня есть запрос в хранимой процедуре, которая вызывает некоторые связанные серверы с некоторым динамическим SQL.Я понимаю, что EF это не нравится, поэтому я специально перечислил все столбцы, которые будут возвращены.И все же это не нравится.Что я здесь не так делаю?Я просто хочу, чтобы EF мог определять столбцы, возвращенные из хранимой процедуры, чтобы я мог создавать нужные мне классы.

Пожалуйста, посмотрите следующий код, который составляет последние строки моей хранимой процедуры:

SELECT
    #TempMain.ID,
    #TempMain.Class_Data,
    #TempMain.Web_Store_Class1,
    #TempMain.Web_Store_Class2,
    #TempMain.Web_Store_Status,
    #TempMain.Cur_1pc_Cat51_Price,
    #TempMain.Cur_1pc_Cat52_Price,
    #TempMain.Cur_1pc_Cat61_Price,
    #TempMain.Cur_1pc_Cat62_Price,
    #TempMain.Cur_1pc_Cat63_Price,
    #TempMain.Flat_Length,
    #TempMain.Flat_Width,
    #TempMain.Item_Height,
    #TempMain.Item_Weight,
    #TempMain.Um,
    #TempMain.Lead_Time_Code,
    #TempMain.Wp_Image_Nme,
    #TempMain.Wp_Mod_Dte,
    #TempMain.Catalog_Price_Chg_Dt,
    #TempMain.Description,
    #TempMain.Supersede_Ctl,
    #TempMain.Supersede_Pn,
    TempDesc.Cust_Desc,
    TempMfgr.Mfgr_Item_Nbr,
    TempMfgr.Mfgr_Name,
    TempMfgr.Vendor_ID
FROM
    #TempMain
        LEFT JOIN TempDesc ON #TempMain.ID = TempDesc.ID
        LEFT JOIN TempMfgr ON #TempMain.ID = TempMfgr.ID

Ответы [ 13 ]

144 голосов
/ 20 августа 2011

EF не поддерживает импорт хранимых процедур, которые создают набор результатов из:

  • Динамические запросы
  • Временные таблицы

Причина в том, чтоимпортировать процедуру EF должна выполнить ее .Такая операция может быть опасной, потому что она может вызвать некоторые изменения в базе данных.По этой причине EF использует специальную команду SQL перед выполнением хранимой процедуры:

SET FMTONLY ON

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

У вас есть два варианта (кроме одного, который требует переписывания хранимой процедуры, чтобы не использовать этиfeatures):

  • Определить возвращаемый сложный тип вручную (думаю, он должен работать)
  • Использовать хак и просто добавить хранимую процедуру в ее начало SET FMTONLY OFF.Это позволит нормальному выполнению остальной части кода вашего SP.Просто убедитесь, что ваш SP не изменяет никакие данные, потому что эти изменения будут выполнены во время импорта!После успешного импорта удалите этот хак.
26 голосов
/ 25 февраля 2013

Добавление этого нелогичного блока кода решило проблему.Даже если он никогда не будет нажимать

IF 1=0 BEGIN
    SET FMTONLY OFF
END

Почему мой набранный набор данных не похож на временные таблицы?

12 голосов
/ 12 ноября 2013

Или вы можете создать пользовательский тип таблицы и вернуть его.

CREATE TYPE T1 AS TABLE 
( ID bigint NOT NULL
  ,Field1 varchar(max) COLLATE Latin1_General_CI_AI NOT NULL
  ,Field2 bit NOT NULL
  ,Field3 varchar(500) NOT NULL
  );
GO

Тогда в процедуре:

DECLARE @tempTable dbo.T1

INSERT @tempTable (ID, Field1, Field2, Field3)
SELECT .....

....

SELECT * FROM @tempTable

Теперь EF должен распознавать тип возвращаемых столбцов.

2 голосов
/ 29 августа 2015

Как отметили некоторые другие, убедитесь, что процедура действительно выполняется. В частности, в моем случае я успешно и без ошибок выполнял процедуру в SQL Server Management Studio, совершенно забыв, что вошел в систему с правами администратора. Как только я попытался запустить процедуру с использованием основного пользователя моего приложения, я обнаружил, что в запросе есть таблица, к которой у этого пользователя нет прав доступа.

1 голос
/ 30 июля 2014

В дополнение к тому, что сказал @tmanthley, убедитесь, что ваша хранимая процедура действительно работает, сначала запустив ее в SSMS. Я импортировал некоторые хранимые процедуры и забыл о паре зависимых скалярных функций, которые заставили EF определить, что процедура не вернула столбцы. Похоже на ошибку, которую я должен был поймать ранее, но EF не дает вам сообщение об ошибке в этом случае.

1 голос
/ 27 мая 2014

оба решения: 1- Определить возвращаемый сложный тип вручную (я думаю, он должен работать). 2- Использовать хак и просто добавить добавленную хранимую процедуру в ее начало. УСТ. FMTONLY OFF.

не работает ся в какой-то процедуре, однако она работала с другой!

моя процедура заканчивается этой строкой:

SELECT machineId, production [AProduction]
        , (select production FROM #ShiftBFinalProd WHERE machineId = #ShiftAFinalProd.machineId) [BProduction]
        , (select production FROM #ShiftCFinalProd WHERE machineId = #ShiftAFinalProd.machineId) [CProduction]
     FROM #ShiftAFinalProd
     ORDER BY machineId

Спасибо

1 голос
/ 08 сентября 2012

Интересное примечание: у меня была та же проблема, которую я впервые решил с помощью табличных переменных, а не временных таблиц (только для импорта).Это не было особенно интуитивно для меня и отбросило меня, когда я впервые наблюдал за моими двумя SProcs: один с использованием временных таблиц, а другой с переменными таблиц.

(УСТАНОВЛЕНО ВЫКЛЮЧЕНО FMTONLY никогда не работало для меня, поэтому я просто временно изменил свои SProcs, чтобы получить информацию о столбце, вместо того, чтобы беспокоиться о хакерской стороне EF просто как к вашему сведению.)

Моим лучшим вариантом было просто вручную создать сложный тип и сопоставить импорт функции с ним.Работал великолепно, и единственное отличие заключалось в том, что в конструктор был добавлен дополнительный FactoryMethod для создания свойств.

1 голос
/ 28 августа 2012

Что бы я добавил, это:

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

У моей хранимой процедуры было 2 параметра с плавающей запятой, и они ничего не возвращали, когда оба параметра были бы равны 0.

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

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

0 голосов
/ 22 мая 2018

Entity Framework будет пытаться получить столбцы, выполняя хранимую процедуру, передавая NULL для каждого аргумента.

  1. Пожалуйста, убедитесь, что хранимая процедура вернет что-то при любых обстоятельствах. Обратите внимание, что для Entity Framework было бы разумнее выполнить сохраненный процесс со значениями по умолчанию для аргументов, в отличие от NULL.

  2. ER выполняет следующие действия для получения метаданных таблицы:

    УСТАНОВИТЬ ТОЛЬКО НА

  3. Это нарушит вашу хранимую процедуру при различных обстоятельствах, в частности, если она использует временную таблицу.

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

    УСТАНОВЛЕНО ВЫКЛЮЧЕНО;

Это сработало для меня - надеюсь, это сработает и для вас.

Ссылается с https://social.msdn.microsoft.com/Forums/en-US/e7f598a2-6827-4b27-a09d-aefe733b48e6/entity-model-add-function-import-stored-procedure-returns-no-columns?forum=adodotnetentityframework

0 голосов
/ 17 января 2017

В платформе Entity при получении информации о столбце sql выполняет процедуру с передачей нулевых значений в параметре.Поэтому я по-разному обработал нулевой регистр, создав временную таблицу со всеми необходимыми столбцами и возвращая все столбцы без значения, когда в процедуру передается нулевой.

В моей процедуре был динамический запрос, что-то вроде

declare @category_id    int
set @category_id = (SELECT CATEGORY_ID FROM CORE_USER where USER_ID = @USER_ID)
declare @tableName varchar(15)
declare @sql VARCHAR(max)     
declare  @USER_IDT  varchar(100)    
declare @SESSION_IDT  varchar(10)

 IF (@category_id = 3)     
set @tableName =  'STUD_STUDENT'
else if(@category_id = 4)
set @tableName = 'STUD_GUARDIAN'


if isnull(@tableName,'')<>'' 
begin

set @sql  = 'SELECT  [USER_ID], [FIRST_NAME], SCHOOL_NAME, SOCIETY_NAME, SCHOOL_ID,
SESSION_ID, [START_DATE], [END_DATE]
from  @tableName
....
EXECUTE   (@sql)
END

ELSE
BEGIN
SELECT  * from #UserPrfTemp
END

Я не получал информацию о столбце в моем случае после использования установленного трюка FMTONLY OFF.

Это временная таблица, которую я создал для получения пустых данных.Теперь я получаю информацию столбца

Create table #UserPrfTemp
(
[USER_ID] bigint, 
[FIRST_NAME] nvarchar(60),
SCHOOL_NAME nvarchar(60),
SOCIETY_NAME nvarchar(200)
.....
}
...