【问题标题】:OUTPUT from Stored Procedure using Azure Mobile Custom API使用 Azure 移动自定义 API 从存储过程输出
【发布时间】:2018-02-21 21:36:32
【问题描述】:

我有一个存储过程,它向表中添加一个新条目并将 ID(作为 nvarchar(255))输出到 @NewID。我可以使用 Postman 对 asp.net 后端执行该过程,但我无法获得输出...我有几个存储过程,它们都工作得很好,只是弄清楚如何在 C# Post 方法中捕获输出.

为了澄清,我正在尝试执行存储过程并使用实体框架通过 Web 服务捕获输出。这是在 Azure 移动服务 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

自定义 ApiController

   [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";

                }
            }
        }

【问题讨论】:

  • 1. Id 在数据库中的类型是什么?可能是您遇到了选角问题。 2.将SELECT @NewID =替换为SET @NewID =并进行测试。
  • 存储过程工作正常。我可以在 SQL 中得到 @NewID 输出就好了。问题出在 C# Api Post 上。没有很多信息或示例。
  • 好吧,你做错了。你永远不应该从 action 方法中调用 proc。你应该至少拥有你的 DAL。但是,关于现在的问题,你测试SET了吗?
  • 我不太了解你的双重否定,但我不能使用带有“FROM”的“SET”,我正在从 Web 服务调用存储过程,所以唯一的方法我可以称之为使用 POST(如果这就是您所说的“操作方法”)感谢您尝试提供帮助,但您所说的似乎与我的实际问题没有任何关系
  • 我最初的问题听起来像是存储过程本身返回输出时遇到问题。它工作正常。我已经编辑了这个问题以避免再次混淆。

标签: c# sql entity-framework asp.net-web-api


【解决方案1】:

OUTPUT 关键字添加到您的执行行中,就在@NewID 部分之后,它将起作用:

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

但正如我在 cmets 中提到的,您与代码有很大关系。您永远不应该在操作中触及数据库——您需要一个数据访问层。您最好不要在使用 ORM 时直接调用过程。您最好在您的过程中将SELECT 部分更改为SET (SET @param = (SELECT some FROM some blah blah blah)),依此类推。但它们与问题无关。 OUTPUT 关键字将完成这项工作。

【讨论】:

  • 输出不起作用,已经在许多不同的变体中尝试过,同样,在使用“FROM”时不能使用“SET”。
  • Azure 应用服务使用实体框架,但非常有限。例如,您不能像通常在实体中那样使用存储过程或关系之类的东西。所以我必须以这种方式使用访问数据上下文的自定义 Web api。这是我能找到的唯一方法。如果你知道比伟大更好的方法,请告诉我。在@NewID 之后使用 OUTPUT 是我最初尝试的方式,param8 仍然总是返回一个空字符串。程序直接在sql中返回输出正常。
  • 我能看到的唯一问题是OUTPUT 关键字。我用OUTPUT(当然还有SET)测试了确切的代码,它工作得很好。所以我没有别的想法。 但是,您可以在使用FROM 时使用SET,正如我在回答中指出的那样:SET @NewID = (SELECT Id FROM dbo.SiteEnclosures WHERE EnclosureID = @@IDENTITY); 不要忘记( ) 周围的SELECT 声明。
  • 好的,我会尝试 () 但仍然可以在 MSSMS 中正常工作,返回输出也很好。当您说您测试过它时,您实际上是否使用 Postman 之类的工具通过 Rest/OData 调用针对 asp.net 服务器对其进行了测试?我可以做一个 HTTP Post 并且 SP 将执行得很好,但我无法捕获 OUPUT 参数。如果您严格地说 SQL,这就是小菜一碟。我很肯定这是我在 C# 代码中做错了,如果有人证明不是这样,我会给他们买可乐。
  • SET = () 没有任何区别。这不是 SQL 问题
【解决方案2】:

想通了... SQL SP 参数似乎不是 INPUT 或 OUTPUT 而是 INPUT/OUTPUT。 所以我改变了 Direction = System.Data.ParameterDirection.InputOutput,它现在可以工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多