web-dev-qa-db-fra.com

Comment obtenir des valeurs de retour et des valeurs de sortie à partir d'une procédure stockée avec 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 ...

Répertoire 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);
    }
}

J'appelle ça comme:

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 obtient la sortie pTotalRecords fine, mais aucune valeur de retour, et le second query2 obtient les valeurs de retour mais aucun paramètre de sortie.

Dans EF 6, nous avions l'habitude d'utiliser SqlQuery pour effectuer les deux actions en une seule commande. Comment puis-je faire la même chose dans EF core?

MIS &AGRAVE; JOUR:

Temporairement, je lance 2 requêtes, une pour obtenir le paramètre de sortie et une pour le jeu de résultats.

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

J'ai fait quelque chose comme ça: - 

- Ma procédure stockée: 

CREATE PROCEDURE p1
AS
     BEGIN            
        RETURN 29
     END
GO

Code 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 

J'espère que cela t'aides

4
kepung

Je travaille à convertir du code EF6 en EF Core et j'ai rencontré le même problème. Dans Microsoft.EntityFrameworkCore version 2.1.0, l'utilisation suivante de FromSql() renvoie un ensemble de résultats et définit le paramètre de sortie. Vous devez utiliser .ToList() pour forcer le proc à s'exécuter immédiatement, renvoyant ainsi les résultats et le paramètre de sortie.

Voici un exemple de ma classe 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;
}

Le proc stocké renvoie l'entité suivante:

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

Voici le proc stocké:

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

Espérons que toute personne rencontrant ce message à l'avenir le trouve utile.

1
tbetts42