Oracle
 sql >> Base de données >  >> RDS >> Oracle

Appel de la procédure stockée Oracle à l'aide d'Entity Framework avec le paramètre de sortie ?

Dans ce cas, vous ne devriez pas appeler :

var query = ctx.Database.SqlQuery<CmdRegisterAssetDto>(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);

Mais appelez plutôt :

var result = ctx.Database.ExecuteSqlCommand(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);

Notez que la seule différence efficace est que SqlQuery<CmdRegisterAssetDto> a été remplacé par ExecuteSqlCommand . Cela signifie également que le DTO est inutile. Sinon, votre code semble fonctionner. Voici votre code d'origine dans son intégralité avec les modifications que j'ai mentionnées :

string projectName = "EXCO";
string location = "ANYWHERE";
string countryCode = "XX";

using (var ctx = new RAContext())
{
    var projectNameParam = new OracleParameter("inProjectName", OracleDbType.Varchar2, projectName, ParameterDirection.Input);
    var countryCodeParam = new OracleParameter("inCountryCode", OracleDbType.Varchar2, countryCode, ParameterDirection.Input);
    var locationParam = new OracleParameter("inLocation", OracleDbType.Varchar2, location, ParameterDirection.Input);
    var assetRegisteredParam = new OracleParameter("OutAssetRegistered", OracleDbType.Varchar2, ParameterDirection.Output);

    var sql = "BEGIN RA.RA_RegisterAsset(:inProjectName, :inCountryCode, :inLocation, :OutAssetRegistered); END;";
    var result = ctx.Database.ExecuteSqlCommand(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);

    assetRegistered = (string)assetRegisteredParam.Value;
}

Pour prouver ma théorie, j'ai reproduit le comportement nul que vous rencontrez, puis j'ai apporté ce changement. Cela a duré un peu (probablement pour laisser EF passer à la vitesse supérieure), mais s'est ensuite exécuté rapidement à chaque fois par la suite. Dans chaque cas, j'ai trouvé une valeur en attente dans le paramètre out.

Si quelqu'un rencontre des problèmes, il existe une variante à long terme qui s'occupe des détails du script pour vous :

string projectName = "EXCO";
string location = "ANYWHERE";
string countryCode = "XX";

using (var ctx = new RAContext())
using (var cmd = ctx.Database.Connection.CreateCommand())
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "RA.RA_REGISTERASSET";

    var projectNameParam = new OracleParameter("inProjectName", OracleDbType.Varchar2, projectName, ParameterDirection.Input);
    var countryCodeParam = new OracleParameter("inCountryCode", OracleDbType.Varchar2, countryCode, ParameterDirection.Input);
    var locationParam = new OracleParameter("inLocation", OracleDbType.Varchar2, location, ParameterDirection.Input);
    var assetRegisteredParam = new OracleParameter("OutAssetRegistered", OracleDbType.Varchar2, ParameterDirection.Output);
    cmd.Parameters.AddRange(new[] { projectNameParam, countryCodeParam, locationParam, assetRegisteredParam });

    cmd.Connection.Open();
    var result = cmd.ExecuteNonQuery();
    cmd.Connection.Close();

    assetRegistered = (string)assetRegisteredParam.Value;
}

Après coup, vous pouvez techniquement utiliser votre solution d'origine si vous appelez la requête immédiatement après (c'est-à-dire query.FirstOrDefault() ). La valeur de retour de la requête serait toujours nulle, mais votre paramètre out serait au moins rempli. En effet, les requêtes EF utilisent une exécution différée.