简体   繁体   中英

How to return a value from a stored procedure to EF

I'm attempting to call a stored proc through EF and retrieve a return value from the stored proc. I've used this answer as a guide. Here is my stored proc:

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

--DO STUFF

SET @result = 0
END

Here is how I'm calling it from 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
}

I'm getting this error message:

The data reader has more than one field. Multiple fields are not valid for EDM primitive or enumeration types

What am I doing wrong?

Try select @result before end of procedure.

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

--DO STUFF

SET @result = 0
Select @result
END

Hope it works.

Try adding .First(); to the end...

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

I don't this you need First() here either since you're returning a single value, this would only work with an IEnumerable - but double check.

var wasSuccessful = result == 1;

I wanted to return the new id of an inserted row with a stored procedure. So I also made an OUTPUT parameter. In C# with EF6 I got it as following:

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);

The name of the variable in the stored procedure needs to match the one with calling the constructor of 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

将ParameterDirection.Output更改为ParameterDirection.ReturnValue

If nothing works then you can try this alternative approach:

  1. Compute the result in PROC and save it in a table in database
  2. Read the data from that table in EF code.

However, if you have a concurrent system that can run many such EF codes in parallel then ofcourse your stored proc needs become more sophisticated to handle concurrency.

Thanks, hope this might help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM