2017-04-25 133 views
2

我在我的應用程序中使用了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} 

基本上這就是我期待的...任何幫助嗎?

回答

0

這裏是如何從一個存儲過程得到多個結果集的例子,如果你是OK使用ADO.NET:

Return multiple recordsets from stored proc in C#

你必須拋棄在這種情況下,輸出參數,雖然。

+0

我知道有在ADP.net一些可能性,但嘗試使用EF核心來實現它。不知何故,我的架構師喜歡用它來等待異步web api動作 –

1

這應該起作用。這一次,我不僅填補一個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 ,實際上,代碼非常相似。

+0

..看起來像我不能在asp.net核心中使用SqlDataAdapter和DataTable http://stackoverflow.com/questions/38536339/sqldataadapter-missing-in- A-ASP-淨核項目 –

1

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