Подтвердить что ты не робот

Почему инфраструктура Entity Framework не видит мою колонтитулу хранимой процедуры?

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

The Proc:

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
4b9b3361

Ответ 1

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

SET FMTONLY OFF

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

Ответ 2

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

  • При выполнении функции import → Get Column Information... Visual Studio выполняет хранимый процесс со всеми значениями параметра как NULL (вы можете перекрестно проверить это через MS SQL Profiler).

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

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

В вашем случае хранимые параметры proc не являются нулевыми, поэтому вызов 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/

Ответ 3

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

IF (1=2)
    SET FMTONLY OFF

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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" ).

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

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

Ответ 7

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

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

удачи/

Ответ 8

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

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

Ответ 9

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

    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, Type FROM #T

Я надеюсь, что это поможет кому-то там.