2013-05-16 1 views
35

Предположит следующее:EF не может сделать вывод возврата схемы из хранимой процедуры выбора из таблицы #temp

CREATE PROCEDURE [MySPROC] 
AS 
BEGIN 

CREATE TABLE #tempSubset(
    [MyPrimaryKey] [bigint] NOT NULL, 
    [OtherColumn] [int]  NOT NULL) 

INSERT INTO #tempSubset (MyPrimaryKey, OtherColumn) 
    SELECT SomePrimaryKey, SomeColumn 
    FROM SomeHugeTable 
    WHERE LimitingCondition = true 

SELECT MyPrimaryKey, OtherColumn 
FROM #tempSubset 
WHERE SomeExpensiveCondition = true 

END 

Когда я произвожу функцию импорт или карты типа возвращаемого значения, EF не создает сложный типа или говорит мне:

Выбранная хранимая процедура или функция не возвращает столбцы

Как преодолеть это?

Другие ответы предполагают using table variables (не собирается делать это по соображениям производительности) faking the return schema and commenting out the real stored procedure, другие предполагают doing similar with views ... но должен быть способ сделать это без необходимости добавлять излишнюю нагрузку или требуя, чтобы я сломать хранимую процедуру обновить модель?

ответ

54
CREATE PROCEDURE [MySPROC] 
AS 
BEGIN 

--supplying a data contract 
IF 1 = 2 BEGIN 
    SELECT 
     cast(null as bigint) as MyPrimaryKey, 
     cast(null as int) as OtherColumn 
    WHERE 
     1 = 2 
END 

CREATE TABLE #tempSubset(
    [MyPrimaryKey] [bigint] NOT NULL, 
    [OtherColumn] [int]  NOT NULL) 

INSERT INTO #tempSubset (MyPrimaryKey, OtherColumn) 
    SELECT SomePrimaryKey, SomeColumn 
    FROM SomeHugeTable 
    WHERE LimitingCondition = true 

SELECT MyPrimaryKey, OtherColumn 
FROM #tempSubset 
WHERE SomeExpensiveCondition = true 

END 

Обеспечение контракта данных лжа для результирующего набора является самым простым, чистым и быстрым способом, чтобы заботиться о проблеме. Эта же проблема существует и в элементах управления источниками данных в SSIS. .NET прочитает набор результатов из недостижимого раздела «контракт» запроса и предоставит метаданные для сложного типа. Отсутствие влияния на производительность и отсутствие необходимости комментировать SQL, который выполняет фактическую работу.

+0

работал большой, и намного лучше, чем те альтернативы! спасибо;) – JoeBrockhaus

+0

Испытали и отлично поработали! Добавлю скрипт, который я использую для генерации моих CREATE PROCEDURES – SleepyBoBos

+3

Обратите внимание, что если вы создадите сложный тип в своей модели, после предоставления контракта данных в этом формате, свойства будут обладать нулевым значением, то есть «public Nullable MyProperty {get; задавать;})'. Это нормально, поскольку он будет обрабатывать случай, когда значение столбца db равно null. Если вы делаете что-то вроде «SELECT 1 AS [MyProperty column]» в контракте, свойство будет «public int MyProperty {get; задавать; } '(вы должны фактически удалить сложный тип класса SleepyBoBos

39

Добавление этого значения в начало определения хранимой процедуры:

SET FMTONLY OFF
разрешало модели выводить схему из временной таблицы без проблем. В качестве бонуса он не требует дополнительного обслуживания для контракта.

Пример:

SET FMTONLY OFF 

CREATE TABLE #tempTable (
    ... 
) 

... 

SELECT * FROM #tempTable 
+0

Это то, что мне нужно ... – Mayank

+1

Далеко и прочь самое простое и быстрое решение. Спасибо. – Xipooo

+0

Спасибо. Очень чистое решение. – Ashby

10

Решение 1 использовать таблицу переменной вместо временной таблицы.

Решение 2 Используйте Set FMTONLY off; SQL в процедуре, и вы получите информацию о столбцах для создания нового сложного типа.

Решение 3 Это нехороший способ, но это очень простой способ. Просто добавьте оператор select с фиктивными данными, и он не будет выполняться, потому что 1 = 0.

вы можете проверить детали на this link

+1

Я пробовал все 3 подхода. Ни один из них не работал. Поскольку я всегда опоздал на 2 дня, и я потратил на это 2 часа. Мне нужно двигаться дальше. Мое временное решение будет рассматривать детали модели для изменения составного типа (найти процедуру и переменную) и вручную изменить с int32 на строку. Это плохая идея. Если обновление, оно будет потеряно. Я даже не могу документировать его, чтобы напомнить другим разработчикам. Любой узнает, что происходит. Пожалуйста, пусть все знают. Я использую VS 2015, EF 6, SQL Server 2016. TX – user12345