且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用EF Core获取存储过程的输出参数值?

更新时间:2023-09-11 21:35:58

这应该是正常的。这一次我只填写了一个DataTable,但是可以使用多个DataTable填充DataSet

 使用(SqlConnection connection = new SqlConnection(_customerContext .Database.Connection.ConnectionString))
{
SqlCommand cmd = new SqlCommand(dbo.usp_CustomerAll_sel,connection);
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add(new SqlParameter(@ SomeOutput,SqlDbType.BigInt){Direction = ParameterDirection.Output,Value = -1});

if(cmd.Connection.State!= ConnectionState.Open)
{
cmd.Connection.Open();
}


connection.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter.Fill(dt);

long SomeOutput =(long)cmd.Parameters [@ SomeOutput]。

connection.Close();
}

由于您不能在.net内核中使用SqlDataAdapter,因此可以使用第三方图书馆可以获得相同的结果,例如 NReco.Data
,实际上,代码很相似。


I am using Asp.net core and EF core in my application. Basically I want to get multiple result set from a single stored procedure. Tried to search it for last 2 days no such luck. Tried to figure out a work around to resolve it..

This is my stored procedure:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[usp_CustomerAll_sel]
    @SomeOutput int OUT
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * 
    FROM [dbo].[Customer]

    SELECT @SomeOutput = @@rowcount + 25 --This number 25 is a variable from a complex query but always an integer
END

I have 2 records in that table, so basically it should return a table of customer type and output parameter should return 27..

Now from my .net code what I have tried so far

[HttpGet]
public async Task<Tuple<IEnumerable<Customer>, int>> GetAllCustomer()
{
    var votesParam = new SqlParameter
            {
                ParameterName = "SomeOutput",
                Value = -1,
                Direction = ParameterDirection.Output
            };

    var y = await _customerContext.Customers.FromSql("usp_CustomerAll_sel @SomeOutput out", votesParam).ToArrayAsync();

    return new Tuple<IEnumerable<Customer>, int>(y, (int)votesParam.Value);
}

Above one returning me the list but I am not getting the value of output parameter from DB .(int)votesParam.Value is showing null

Now if I use ExecuteNonQueryAsync, then I am getting the output parameter but not the actual data

private async Task ExecuteStoredProc()
{
    DbCommand cmd = _customerContext.Database.GetDbConnection().CreateCommand();

    cmd.CommandText = "dbo.usp_CustomerAll_sel";
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Add(new SqlParameter("@SomeOutput", SqlDbType.BigInt) { Direction = ParameterDirection.Output, Value = -1 });

    if (cmd.Connection.State != ConnectionState.Open)
    {
        cmd.Connection.Open();
    }

    await cmd.ExecuteNonQueryAsync();

    long SomeOutput = (long)cmd.Parameters["@SomeOutput"].Value;
}

Is there any way to get both result set and the output parameter and return as a tuple?

When I just put the hard coded value then it's looks like

[HttpGet]
public async Task<Tuple<IEnumerable<Customer>, int>> GetAllCustomer()
{
    var votesParam = new SqlParameter
    {
        ParameterName = "SomeOutput",
        Value = -1,
        Direction = ParameterDirection.Output
    };

    var y = await _customerContext.Customers.FromSql("usp_CustomerAll_sel @SomeOutput out", votesParam).ToArrayAsync();
    return new Tuple<IEnumerable<Customer>, int>(y, **25**);
}

And result like

{"item1":[{"customerId":1,"customerName":"Cus1"},{"customerId":2,"customerName":"Cus2"}],"item2":27}

Basically this is what I am looking for... Any help?

This should work. This time I filled only a DataTable, but you can fill a DataSet with multiples DataTables

using (SqlConnection connection  = new SqlConnection(_customerContext.Database.Connection.ConnectionString))
                {
                    SqlCommand cmd = new SqlCommand("dbo.usp_CustomerAll_sel", connection);
                    cmd.CommandType = CommandType.StoredProcedure;

                    cmd.Parameters.Add(new SqlParameter("@SomeOutput", SqlDbType.BigInt) { Direction = ParameterDirection.Output, Value = -1 });

                    if (cmd.Connection.State != ConnectionState.Open)
                    {
                        cmd.Connection.Open();
                    }


                    connection.Open();
                    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    adapter.Fill(dt);

                    long SomeOutput = (long)cmd.Parameters["@SomeOutput"].Value;

                    connection.Close();
                }

Since you can't use SqlDataAdapter in .net core, you can use a third party library to archieve the same result, like NReco.Data , actually, the code is pretty similar.