【问题标题】:How to return a value from a stored procedure to EF如何将值从存储过程返回到 EF
【发布时间】:2016-02-12 00:15:25
【问题描述】:

我正在尝试通过 EF 调用存储过程并从存储过程中检索返回值。我使用this 回答作为指导。这是我的存储过程:

CREATE PROCEDURE [dbo].[usp_test]
(
    @result int OUT
)
AS
BEGIN

--DO STUFF

SET @result = 0
END

这是我从 EF 中调用它的方式:

var status = new SqlParameter
{
    ParameterName = "result",
    DbType = DbType.Int32,
    Direction = ParameterDirection.Output 
};
var result = context.Database.SqlQuery<int>("EXEC usp_test @result", status);
var wasSuccessful = result.First() == 1;
if (!wasSuccessful)
{
    //DO STUFF
}

我收到此错误消息:

数据读取器有多个字段。多个字段对 EDM 基元或枚举类型无效

我做错了什么?

【问题讨论】:

  • 您是否在存储过程中执行了 SELECT 操作?如果是这样,这是您的返回类型。作为提示 - 您必须先使用结果集,然后才能获取输出参数的值。
  • @Pawel:整个存储过程都存在问题。我也试过SET @result = 0
  • 好的。 --DO STUFF 表示您正在正文中执行某些操作,并且您没有设置输出参数的值,这就是为什么我不知道这是否是一个完整的过程...
  • @Pawel:很抱歉造成混乱。我现在在做什么(更新)你如何在 SP 中设置输出参数?
  • 我现在不记得了,但它可能是 EF 总是期望一个结果集。你能在你的存储过程中添加一个虚拟的SELECT 0 看看它是否有效吗?

标签: c# sql sql-server entity-framework


【解决方案1】:

在程序结束前尝试select @result

CREATE PROCEDURE [dbo].[usp_test]
(
    @result int OUT
)
AS
BEGIN

--DO STUFF

SET @result = 0
Select @result
END

希望它有效。

【讨论】:

  • 设置@result后SP末尾的SELECT做到了。谢谢!
【解决方案2】:

我想用存储过程返回插入行的新 id。所以我也做了一个OUTPUT参数。在带有 EF6 的 C# 中,我得到它如下:

using System.Data.Entity.Core.Objects;
...
db = new myEntities1();
ObjectParameter returnId = new ObjectParameter("returnId", DbType.Int64);
db.postLogItem("New item.", returnId);
MessageBox.Show("Logitem added. New returnId: " + (int)returnId.Value);

存储过程中的变量名称需要与调用ObjectParameter的构造函数的名称相匹配。

CREATE PROCEDURE [dbo].[postLogItem]
    @description nvarchar(200),
    @returnId bigint OUTPUT
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO dbo.LogItem 
        (
            time,
            description
        )
        VALUES
        (
            GETDATE(),
            @description
        );

    SET @returnId = SCOPE_IDENTITY();
END

【讨论】:

    【解决方案3】:

    尝试在末尾添加.First();...

    var result = context.Database.SqlQuery<int>("EXEC usp_test @result", status).First(); 
    

    我在这里也不需要First(),因为您返回的是单个值,这仅适用于 IEnumerable - 但请仔细检查。

    var wasSuccessful = result == 1;
    

    【讨论】:

      【解决方案4】:

      将 ParameterDirection.Output 更改为 ParameterDirection.ReturnValue

      【讨论】:

        【解决方案5】:

        如果没有任何效果,那么您可以尝试这种替代方法:

        1. 在 PROC 中计算结果并将其保存在数据库中的表中
        2. 以 EF 代码从该表中读取数据。

        但是,如果您有一个可以并行运行许多此类 EF 代码的并发系统,那么您的存储过程当然需要更复杂地处理并发。

        谢谢,希望对你有帮助。

        【讨论】:

        • 这只是我通常不惜一切代价避免的那种骇人听闻的解决方案。
        猜你喜欢
        • 1970-01-01
        • 2015-04-14
        • 1970-01-01
        • 2016-04-26
        • 1970-01-01
        • 2017-10-11
        • 1970-01-01
        • 1970-01-01
        • 2020-01-07
        相关资源
        最近更新 更多