Почему Entity Framework не видит информацию о столбце моей хранимой процедуры? - PullRequest
30 голосов
/ 13 мая 2011

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

Процесс:

ALTER PROCEDURE [healthc].[ev_kc_Products_Search]
(
    @SearchString   VARCHAR(1000)
)
AS
SET NOCOUNT ON

    DECLARE @SQL    VARCHAR(max),
        @SQL1   VARCHAR(max),
        @Tag    VARCHAR(5)

    CREATE TABLE #T
    (   ID      INT,
        VendorName  VARCHAR(255),
        ItemName        VARCHAR(255),
        Type        VARCHAR(2),
        Sequence        TINYINT
    )


 SET @SQL = '

    INSERT  #T

    SELECT  VendorID ID,
        Name VendorName,
        NULL ItemName,
        ''V'' Type,
        0 Sequence
    FROM    tblVendors
    WHERE   '+REPLACE(@SQL1,@Tag,'Name')+'

    UNION ALL

    BLAH BLAH BLAH'


 EXEC(@SQL)


 SELECT ID, VendorName, ItemName, Type FROM #T

Ответы [ 9 ]

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

Попробуйте добавить эту строку в начало вашей хранимой процедуры:

SET FMTONLY OFF

Вы можете удалить это после завершения импорта.

36 голосов
/ 09 ноября 2012

Что здесь происходит за кулисами?

  1. При выполнении импорта функции -> Получить информацию столбца ... Visual Studio выполняет сохраненный процесс со всеми значениями параметров как NULL (вы можете перепроверить это через MS SQL Profiler).

  2. При выполнении шага 1 возвращаемые столбцы сохраненной процедуры возвращаются с информацией о типе и длине данных.

  3. После получения информации о столбце нажатие на кнопку «Создать новый сложный тип» создает состязательный тип SP в конфликте.

В вашем случае хранимые параметры процедуры не обнуляются, поэтому вызов Visual Studio завершается неудачно и не возвращает столбцов.

Как с этим справиться?

IF (1=0) 
BEGIN 
    SET FMTONLY OFF 
    if @param1 is null and @param2 is null then
        begin
            select
            cast(null as varchar(10)) as Column1,
            cast(null as bit) as Column2,
            cast(null as decimal) as Column3
        END
END   

Если быть точным (в вашем случае):

IF (1=0) 
BEGIN 
    SET FMTONLY OFF 
    if @SearchString is null then
        BEGIN
            select
            cast(null as int) as ID,
            cast(null as varchar(255)) as VendorName,
            cast(null as varchar(255)) as ItemName,
            cast(null as varchar(2)) as Type
        END
END   

Ссылка: http://mysoftwarenotes.wordpress.com/2011/11/04/entity-framework-4-%E2%80%93-the-selected-stored-procedure-returns-no-columns-part-2/

6 голосов
/ 14 ноября 2016

в полноте и простом ответе @benshabatnoam, просто введите следующий код в начале:

IF (1=2)
    SET FMTONLY OFF

Примечание: это работает в EF 6.1.3 и Visual Studio 2015 Update 3

3 голосов
/ 20 августа 2014

У вас возникла эта проблема из-за временной таблицы.Все, что вам нужно сделать, это: 1. Измените вашу хранимую процедуру, чтобы она возвращала select statemant без временной таблицы.2. Перейдите к функции import и получите информацию о столбце.3. Измените вашу сохраненную процедуру обратно на оригинальную.

2 голосов
/ 06 сентября 2015

Если вы используете временную таблицу, Entity (EDMX) не может понять, что происходит.

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

удачи /

1 голос
/ 29 августа 2014

Я бы хотел добавить кое-что к ответу Судханшу Сингха: он работает очень хорошо, но если у вас есть более сложные структуры, объедините его с объявлением таблицы.

Я успешно использовал следующее (поместите егов самом начале сохраненной процедуры):

CREATE PROCEDURE [EY].[MyStoredProc] 
AS
BEGIN

SET NOCOUNT ON;

IF (1=0) 
BEGIN 
    SET FMTONLY OFF 
        BEGIN
            -- declaration + dummy query 
            -- to allow EF obtain complex data type:
            DECLARE @MyStoredProcResult TABLE(
                ID      INT,
                VendorName  VARCHAR(255),
                ItemName    VARCHAR(255),
                Type        VARCHAR(2),
                Sequence    TINYINT
                );
            SELECT * FROM @MyStoredProcResult WHERE (1=0)
        END
END   

-- your code follows here (SELECT ... FROM ...)
-- this code must return the same columns/data types
--
-- if you require a temp table / table variable like the one above
-- anyway, add the results during processing to @MyStoredProcResult
-- and then your last statement in the SP can be
-- SELECT * FROM @MyStoredProcResult
END

Обратите внимание , что 1=0 гарантирует, что он никогда не будет выполнен, но EF вычитает структуру из него.

После сохранения вашей хранимой процедуры откройте файл EDMX в Visual Studio, обновите модель данных, перейдите в браузер модели Entity Frameworks.В браузере модели найдите свою хранимую процедуру, откройте диалоговое окно «Редактировать импорт функций», выберите «Возвращает коллекцию ... сложных», затем нажмите кнопку «Получить информацию столбца».

Этодолжна показать структуру, как определено выше.Если это так, нажмите «Создать новый сложный тип», и он создаст его с именем хранимой процедуры, например, «MyStoredProc_Result» (с добавлением «_Result»).

Теперь вы можете выбрать его в выпадающем списке «Возвращает коллекцию ... Комплекс» в том же диалоговом окне.

Когда вам нужно что-то обновить, сначала обновите SP, а затемможете вернуться в диалоговое окно «Редактировать функцию импорта» и нажать кнопку «Обновить» (вам не нужно заново создавать все с нуля).

1 голос
/ 14 июня 2013

В качестве быстрого и грязного способа заставить EF находить столбцы, закомментируйте предложение where в вашем сохраненном процессе (возможно, добавьте TOP 1, чтобы он не возвращал все), добавьте процесс в EF и создайте сложный тип,затем снова раскомментируйте предложение where.

0 голосов
/ 13 июля 2016

Просто добавьте оператор выбора без кавычек, выполните сохраненный процесс, перейдите к обновлению модели, отредактируйте импорт вашей функции и получите информацию о столбце.Это должно заполнить новые столбцы.Обновите набор результатов и вернитесь к сохраненному процессу и удалите только что добавленный список выбора.И выполнить сохраненную процедуру.Таким образом, ваши столбцы будут заполнены в наборе результатов.См. Ниже, где добавить список выбора без кавычек.

    ALTER PROCEDURE [healthc].[ev_kc_Products_Search]
(
    @SearchString   VARCHAR(1000)
)

AS
SET NOCOUNT ON;
SELECT  VendorID ID,
        Name VendorName,
        NULL ItemName,
        ''V'' Type,
        0 Sequence
    FROM    tblVendors

DECLARE @SQL    VARCHAR(max),
    @SQL1   VARCHAR(max),
    @Tag    VARCHAR(5)

CREATE TABLE #T
(   ID      INT,
    VendorName  VARCHAR(255),
    ItemName        VARCHAR(255),
    Type        VARCHAR(2),
    Sequence        TINYINT
)

SET @SQL = '

INSERT  #T

SELECT  VendorID ID,
    Name VendorName,
    NULL ItemName,
    ''V'' Type,
    0 Sequence
FROM    tblVendors
WHERE   '+REPLACE(@SQL1,@Tag,'Name')+'

UNION ALL

BLAH BLAH BLAH'

EXEC (@SQL)

SELECT ID, VendorName,ItemName, введите FROM # T

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 15 февраля 2016

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

CREATE TYPE T1 AS TABLE 
(  ID      INT,
    VendorName  VARCHAR(255),
    ItemName        VARCHAR(255),
    Type        VARCHAR(2),
    Sequence        TINYINT
);
GO

Ваша хранимая процедура теперь будет выглядеть так:

ALTER PROCEDURE [healthc].[ev_kc_Products_Search]
(
@SearchString   VARCHAR(1000)
)
AS
SET NOCOUNT ON

DECLARE @SQL    VARCHAR(max),
    @SQL1   VARCHAR(max),
    @Tag    VARCHAR(5)

@T [schema].T1

SET @SQL = 'SELECT  VendorID ID,
    Name VendorName,
    NULL ItemName,
    ''V'' Type,
    0 Sequence
    FROM    tblVendors
    WHERE   '+REPLACE(@SQL1,@Tag,'Name')+'
    UNION ALL
    BLAH BLAH BLAH'

INSERT INTO @T
EXEC(@SQL)

SELECT ID, VendorName, ItemName, Type FROM @T
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...