使用EF Core获取存储过程的输出参数值?
我在我的应用程序中使用了Asp.net核心和EF核心。基本上我想从单个存储过程中获得多个结果集。试图搜索它最后2天没有这样的运气。试图围绕找出一个工作,解决它..使用EF Core获取存储过程的输出参数值?
这是我的存储过程:
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个记录在该表中,所以基本上它应该返回客户的类型和输出参数表应该从我的.NET代码返回27 ..
现在我迄今
[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);
}
以上人试图返回我的名单,但我没有得到OUTP的价值从DB .(int)votesParam.Value
UT参数显示空
现在,如果我用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}
基本上这就是我期待的...任何帮助吗?
这里是如何从一个存储过程得到多个结果集的例子,如果你是OK使用ADO.NET:
Return multiple recordsets from stored proc in C#
你必须抛弃在这种情况下,输出参数,虽然。
这应该起作用。这一次,我不仅填补一个DataTable,但你可以填补倍数的DataTable DataSet中
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();
}
因为你不能在.NET核心使用SqlDataAdapter的,你可以使用一个第三方库archieve相同的结果,如NReco.Data ,实际上,代码非常相似。
..看起来像我不能在asp.net核心中使用SqlDataAdapter和DataTable http://stackoverflow.com/questions/38536339/sqldataadapter-missing-in- A-ASP-净核项目 –
在EF核心将无法返回从原始的SQL查询的ad-hoc类型,但(他们是这方面的工作),所以首先,你需要锻炼了这个问题,这个类添加到您的项目:
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";
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();
我知道有在ADP.net一些可能性,但尝试使用EF核心来实现它。不知何故,我的架构师喜欢用它来等待异步web api动作 –