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

标签 c# entity-framework asp.net-core entity-framework-core

我在我的应用程序中使用 Asp.net 核心和 EF 核心。基本上我想从一个存储过程中获取多个结果集。过去 2 天试图搜索它,但没有这样的运气。试图找出解决方法..

这是我的存储过程:

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

我在那个表中有 2 条记录,所以基本上它应该返回一个客户类型的表,输出参数应该返回 27..

现在根据我的 .net 代码,到目前为止我已经尝试过

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

上面一个返回列表但我没有从 DB 获取输出参数的值。(int)votesParam.Value 显示为 null

现在如果我使用 ExecuteNonQueryAsync,那么我得到的是输出参数而不是实际数据

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

有没有办法同时获取结果集和输出参数并作为元组返回?

当我只输入硬编码值时,它看起来像

[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**);
}

结果如

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

基本上这就是我要找的...有什么帮助吗?

最佳答案

在 EF Core 中,您还不能从原始 SQL 查询返回临时类型(他们正在处理此问题),因此您需要一个解决此问题的方法。将此类添加到您的项目中:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.EntityFrameworkCore
{

    public static class RDFacadeExtensions
    {
        public static RelationalDataReader ExecuteSqlQuery(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
        {
            var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>();

            using (concurrencyDetector.EnterCriticalSection())
            {
                var rawSqlCommand = databaseFacade
                    .GetService<IRawSqlCommandBuilder>()
                    .Build(sql, parameters);

                return rawSqlCommand
                    .RelationalCommand
                    .ExecuteReader(
                        databaseFacade.GetService<IRelationalConnection>(),
                        parameterValues: rawSqlCommand.ParameterValues);
            }
        }
    }
}

然后您可以调用下面的方法并从您的 SP 获取输出,这是一个示例:

            var _sMsg = new SqlParameter("sMsg", "")
            {
                Direction = ParameterDirection.Output,
                DbType = DbType.String,
                Size = 500
            };

            var sql = "exec sp_foo @sUserId, @sMsg OUTPUT";

            using (var dr = _ctx.Database.ExecuteSqlQuery(sql, _sUserID, _sMsg))
            {
                //here you can retrive your table
                while (dr.DbDataReader.Read())
                {
                    var bar = dr.DbDataReader[0].ToString();
                }

                //here is your OUTPUT
                return _sMsg.Value.ToString();
            }

关于c# - 使用 EF Core 获取存储过程的输出参数值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43621262/

相关文章:

c# - 必须关闭 asp.net datareader

c# - 循环 xaml 元素

c# - 如何为类生成 JSON 示例值,就像 Swagger 所做的示例响应一样?

c# - 将表值参数传递给具有不同字段数的存储过程

c# - 如何在 ASP.NET Core Controller 方法中支持多个 Consumes MIME 类型

c# - 防止在 Entity Framework 上的 TPT 继承中加载子类表行

c# - 在 Heroku 中运行 EF Core 迁移

entity-framework - EF - 为什么不包括对属性的工作

visual-studio-2015 - ASP.NET Identity - 如何以编程方式创建用户时更改密码要求

c# - RazorPages Page Remote 不适用于模型