ВЫВОД из хранимой процедуры с использованием пользовательского API Azure для мобильных устройств

У меня есть хранимая процедура, которая добавляет новую запись в таблицу и ВЫВОДИТ идентификатор (как nvarchar (255)) в @NewID. Я могу просто выполнить процедуру для бэкэнда asp.net с помощью Postman, но я не могу получить ВЫВОД... У меня есть несколько хранимых процедур, и все они работают нормально, просто выясните, как захватить ВЫВОД в методе публикации С#. .

Для пояснения: я пытаюсь выполнить хранимую процедуру и зафиксировать выходные данные, используя инфраструктуру сущностей через веб-службу. Это выполняется на сервере Azure Mobile Service asp.net.

Тестирование хранимой процедуры

ALTER PROCEDURE [dbo].[AddEnclosureKey]
(
    -- Add the parameters for the stored procedure here
    @SpecItemID nvarchar(255),
    @EnclosureType varchar(3) = 'XXX',
    @Comments varchar(50),
    @Elevation varchar(50),
    @ProvidedBy varchar(50),
    @InstalledBy varchar(50),
    @SiteID nvarchar(255) = 'CE359D6F-490B-45E4-BA14-72D20AB757FD',
    @NewID nvarchar(255) OUTPUT
)
AS
IF (@SpecItemID is not null or @SiteID is not null)
    BEGIN

        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;

        -- insert
        INSERT INTO dbo.SiteEnclosureKey(EnclosureKeyComments,EnclosureKeyType, EnclosureKeyElevation,EnclosureKeyProvidedBy,EnclosureKeyInstalledBy,EnclosureKeyItemID,EnclosureKeySiteID)
        VALUES (@Comments,IIF(@EnclosureType = 'XXX',dbo.AutoEnclosureKeyType(@SpecItemID),@EnclosureType), @Elevation, @ProvidedBy, @InstalledBy,@SpecItemID,@SiteID);

        IF @@IDENTITY > 0
        SELECT @NewID = Id FROM dbo.SiteEnclosures WHERE EnclosureID = @@IDENTITY;
        ELSE
        SET @NewID = null

    END
ELSE
    BEGIN
        RETURN 0
    END

Пользовательский API-контроллер

   [MobileAppController]
        public class AddEnclosureKeyController : ApiController
        {
            // POST api
            [HttpPost, Route("api/addenclosurekey")]
            public string Post(string item, string type="XXX", string comments="", string elevation="", string providedby="", string installedby="", string site="CE359D6F-490B-45E4-BA14-72D20AB757FD")
            {
                using (MIIToolsContext context = new MIIToolsContext())
                {
                    //get the database from the context
                    var database = context.Database;

                    //create the sql statement
                    var param1 = new System.Data.SqlClient.SqlParameter("@SpecItemID", item);
                    var param2 = new System.Data.SqlClient.SqlParameter("@EnclosureType", type);
                    var param3 = new System.Data.SqlClient.SqlParameter("@Comments", comments);
                    var param4 = new System.Data.SqlClient.SqlParameter("@Elevation", elevation);
                    var param5 = new System.Data.SqlClient.SqlParameter("@ProvidedBy", providedby);
                    var param6 = new System.Data.SqlClient.SqlParameter("@InstalledBy", installedby);
                    var param7 = new System.Data.SqlClient.SqlParameter("@SiteID", site);
                    var param8 = new System.Data.SqlClient.SqlParameter()
                    {
                        ParameterName = "@NewID",
                        Direction = System.Data.ParameterDirection.Output,
                        SqlDbType = System.Data.SqlDbType.NVarChar,
                        Size = 255
                    };

                    //var result = database.SqlQuery<string>("dbo.AddEnclosureKey @SpecItemID , @EnclosureType , @Comments , @Elevation , @ProvidedBy , @InstalledBy , @SiteID , @NewID OUTPUT", param1, param2, param3, param4, param5, param6, param7, param8);

                    //return NewID.ToString();

                   database.ExecuteSqlCommand("EXEC dbo.AddEnclosureKey @SpecItemID , @EnclosureType , @Comments , @Elevation , @ProvidedBy , @InstalledBy , @SiteID , @NewID OUTPUT", param1, param2, param3, param4, param5, param6, param7, param8);


                    return (string)param8.Value ?? "boo";

                }
            }
        }

person beatnikthedan    schedule 21.02.2018    source источник
comment
1. Какой тип Id в базе данных? может быть у вас проблемы с кастингом. 2. Замените SELECT @NewID = на SET @NewID = и проверьте.   -  person amiry jd    schedule 21.02.2018
comment
Хранимые процедуры работают нормально. Я могу получить вывод @NewID в SQL просто отлично. Проблема связана с C # Api Post. Для этого не так много информации или примеров.   -  person beatnikthedan    schedule 21.02.2018
comment
Ну ты все делаешь не так. Вы никогда не должны вызывать proc из метода действия. Вы должны иметь как минимум свой DAL. НО, о проблеме прямо сейчас, вы тестировали SET?   -  person amiry jd    schedule 21.02.2018
comment
Я действительно не понимаю вас с вашим двойным отрицанием, но я не могу использовать SET с FROM, и я вызываю хранимую процедуру из веб-службы, поэтому единственный способ, которым я могу ее вызвать, - это использовать POST (если это что вы подразумеваете под методом действия) спасибо за попытку помочь, но то, что вы говорите, похоже, не имеет никакого отношения к моему фактическому вопросу   -  person beatnikthedan    schedule 21.02.2018
comment
Мой первоначальный вопрос звучал так, как будто у меня были проблемы с самой хранимой процедурой, возвращающей ВЫВОД. Он работает нормально. Я отредактировал вопрос, чтобы снова избежать путаницы.   -  person beatnikthedan    schedule 21.02.2018


Ответы (2)


Добавьте ключевое слово OUTPUT в строку выполнения сразу после части @NewID, и все заработает:

database.ExecuteSqlCommand("EXEC dbo.AddEnclosureKey @SpecItemID , @EnclosureType , @Comments , @Elevation , @ProvidedBy , @InstalledBy , @SiteID , @NewID OUTPUT", 
                            param1, param2, param3, param4, param5, param6, param7, param8);

Но, как я уже упоминал в комментариях, у вас много общего с кодом. Вы никогда не должны касаться базы данных внутри действия - вам нужен уровень доступа к данным. Вам лучше не вызывать процедуры напрямую при использовании ORM. Вам лучше заменить часть SELECT на SET в вашей процедуре (SET @param = (SELECT some FROM some blah blah blah)) и так далее. Но они не имеют отношения к вопросу. Ключевое слово OUTPUT сделает эту работу.

person amiry jd    schedule 21.02.2018
comment
Вывод не работает, уже пробовал во многих разных вариантах и ​​снова не может использовать SET при использовании FROM. - person beatnikthedan; 21.02.2018
comment
Служба приложений Azure использует инфраструктуру сущностей, но она очень ограничена. Например, вы не можете использовать такие вещи, как хранимые процедуры или отношения, как обычно в сущности. Поэтому я должен сделать это таким образом, используя собственный веб-API, обращающийся к контексту данных. это единственный способ, который я могу найти возможным. Если вы знаете лучший способ, чем великий, покажите мне. Использование OUTPUT после @NewID - это то, как я изначально пытался это сделать, param8 по-прежнему всегда возвращает пустую строку. Процедура возвращает вывод в sql напрямую. - person beatnikthedan; 21.02.2018
comment
Единственная проблема, которую я вижу, это ключевое слово OUTPUT. Я протестировал точный код с OUTPUT (и, конечно, с SET), и он отлично работает. Так что у меня нет другой идеи. НО, вы можете использовать SET при использовании FROM, как я указал в ответе: SET @NewID = (SELECT Id FROM dbo.SiteEnclosures WHERE EnclosureID = @@IDENTITY); Не забывайте ( ) вокруг оператора SELECT. - person amiry jd; 21.02.2018
comment
Хорошо, я попробую (), но все равно отлично работает в MSSMS, отлично возвращает вывод. Когда вы говорите, что протестировали его, вы действительно тестировали его на сервере asp.net с вызовом Rest/OData, используя что-то вроде Postman? Я могу сделать HTTP-сообщение, и SP будет работать нормально, но я не могу зафиксировать параметр OUPUT. это кусок пирога, если вы строго говорите о SQL. Я уверен, что это что-то, что я делаю неправильно в коде C #, если кто-то докажет обратное, я куплю им колу. - person beatnikthedan; 21.02.2018
comment
SET = () не имеет никакого значения. это не проблема SQL - person beatnikthedan; 21.02.2018
comment
Есть вопрос: 1- о том, почему у вас нет результата, о котором я сказал, что понятия не имею. Да, я протестировал его на сервере компании, и он просто работает. 2- Вы сказали, что невозможно использовать SET с FROM, на что я сказал нет, это возможно. Вам просто нужно поместить оператор SELECT в (). Это подход best practice, который я рекомендовал. Так же, как наличие уровня доступа к данным и т. д. Надеюсь найти проблему. Я не вижу других возможностей. - person amiry jd; 21.02.2018
comment
Не слишком сильно бить дохлую лошадь, но: это работает на Entity Framework, и если это не DAL, то я не знаю, что будет, ха-ха. SET против SELECT, да, стандарт ANSI, бла-бла-бла, но все же не проблема, не вопрос, и я специально сказал, что это тестовая хранимая процедура. Спасибо, что потратили на это время, надеюсь, мой ответ поможет кому-то в будущем, потому что у меня почти нет полной документации, чтобы делать то, что я делаю со службой приложений Azure. - person beatnikthedan; 21.02.2018

Разобрался... Параметры SQL SP кажутся не INPUT или OUTPUT, а INPUT/OUTPUT. Итак, я изменил Direction = System.Data.ParameterDirection.InputOutput, и теперь он работает.

person beatnikthedan    schedule 21.02.2018