web-dev-qa-db-ja.com

EF Coreでストアドプロシージャから戻り値と出力値を取得する方法

ALTER PROCEDURE [dbo].[SearchMovies]
    --@Year     int = null,
    @CategoryIds varchar(50) = null,
    @Keywords nvarchar(4000) = null,
    @PageIndex int = 1, 
    @PageSize int = 2147483644,
    @TotalRecords int = null OUTPUT
As ...

EFリポジトリ:

 public class EFRepository<T> : IRepository<T> where T : BaseEntity
{
    private readonly ApplicationDbContext _ctx;
    private  DbSet<T> entities;
    string errorMessage = string.Empty;

    public EFRepository(ApplicationDbContext context)
    {
        this._ctx = context;
        entities = context.Set<T>();
    }     
   ...

    public IQueryable<T> ExecuteStoredProcedureList(string commandText, params object[] parameters)
    {          
        _ctx.Database.ExecuteSqlCommand(commandText, parameters);
        return entities.FromSql(commandText, parameters);
    }
}

私はこれを次のように呼びます:

var pCategoryIds = new SqlParameter()
            {
                ParameterName = "@CategoryIds",
                Value = commaSeparatedCategoryIds,
                DbType = DbType.String
            };
var pKeywords = new SqlParameter()
            {
                ParameterName = "@Keywords",
                DbType = DbType.String,
                Value = name
            };
var pPageIndex = new SqlParameter()
            {
                ParameterName = "@PageIndex",
                DbType = DbType.Int32,
                Value = pageIndex
            };
var pPageSize = new SqlParameter()
            {
                ParameterName = "@PageSize",
                DbType = DbType.Int32,
                Value = pageSize
            };

var pTotalRecords = new SqlParameter();
pTotalRecords.ParameterName = "@TotalRecords";
pTotalRecords.Direction = ParameterDirection.Output;
pTotalRecords.DbType = DbType.Int32;

var query1 = _ctx.Database.ExecuteSqlCommand("dbo.[SearchMovies] " +
                "@CategoryIds, @Keywords, @PageIndex, @PageSize, @TotalRecords OUTPUT", 
                pCategoryIds, pKeywords, pPageIndex, pPageSize, pTotalRecords);

var query2 = _ctx.Set<MovieItem>.FromSql("dbo.[SearchMovies] " +
                    "@CategoryIds, @Keywords, @PageIndex, @PageSize, @TotalRecords OUTPUT",
                    pCategoryIds, pKeywords, pPageIndex, pPageSize, pTotalRecords);

query1は出力pTotalRecordsを取得しますが、戻り値は取得しません。2番目のquery2は戻り値を取得しますが、出力パラメーターは取得しません。

EF 6では、1つのコマンドで両方のアクションを実行するためにSqlQueryを使用していましたが、EFコアで同じようにするにはどうすればよいですか?

[〜#〜]更新[〜#〜]

一時的に、2つのクエリを実行します。1つは出力パラメーターを取得するためのもので、もう1つは結果セットのためのものです。

 public IQueryable<T> ExecuteStoredProcedureList(string commandText, params object[] parameters)
    {          
        _ctx.Database.ExecuteSqlCommand(commandText, parameters);
        return entities.FromSql(commandText, parameters);
    }
8
nam vo

私はこのようなことをしました:-

-私のストアドプロシージャ:

CREATE PROCEDURE p1
AS
     BEGIN            
        RETURN 29
     END
GO

C#コード

SqlParameter[] @params = 
{
   new SqlParameter("@returnVal", SqlDbType.Int) {Direction = ParameterDirection.Output}
 };   


_stagingContext.Database.ExecuteSqlCommand("exec @returnVal=" + storedProcName, @params);

var result = @params[0].Value; //result is 29 

お役に立てれば

13
kepung

私はいくつかのEF6コードをEF Coreに変換する作業をしており、この同じ問題に遭遇しました。 Microsoft.EntityFrameworkCoreバージョン2.1.0では、次のようにFromSql()を使用すると、結果セットが返され、出力パラメーターが設定されます。 .ToList()を使用して、プロシージャをすぐに強制的に実行し、結果と出力パラメータの両方を返す必要があります。

これは私のDbContextクラスのサンプルです:

private DbQuery<ExampleStoredProc_Result> ExampleStoredProc_Results { get; set; }
public IEnumerable<ExampleStoredProc_Result> RunExampleStoredProc(int firstId, out bool outputBit)
{
    var outputBitParameter = new SqlParameter
    {
        ParameterName = "outputBit",
        SqlDbType = SqlDbType.Bit,
        Direction = ParameterDirection.Output
    };

    SqlParameter[] parameters =
    {
        new SqlParameter("firstId", firstId),
        outputBitParameter
    };

    // Need to do a ToList to get the query to execute immediately 
    // so that we can get both the results and the output parameter.
    string sqlQuery = "Exec [ExampleStoredProc] @firstId, @outputBit OUTPUT";
    var results = ExampleStoredProc_Results.FromSql(sqlQuery, parameters).ToList();

    outputBit = outputBitParameter.Value as bool? ?? default(bool);

    return results;
}

ストアドプロシージャは次のエンティティを返します。

public class ExampleStoredProc_Result
{
    public int ID { get; set; }
    public string Name { get; set; }
}

これがストアドプロシージャです。

CREATE PROCEDURE ExampleStoredProc 
    @firstId int = 0,
    @outputBit BIT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;

    SET @outputBit = 1;

    SELECT @firstId AS [ID], 'first' AS [NAME]
    UNION ALL
    SELECT @firstId + 1 AS [ID], 'second' AS [NAME]
END
GO

うまくいけば、将来この投稿に出くわす人なら誰でも、これが役に立つと思います。

2
tbetts42