Oracle
 sql >> Database >  >> RDS >> Oracle

Chiamare la stored procedure Oracle utilizzando Entity Framework con parametro di output?

In questo caso, non dovresti chiamare:

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

Ma invece chiama:

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

Si noti che l'unica differenza effettiva è che SqlQuery<CmdRegisterAssetDto> è stato sostituito con ExecuteSqlCommand . Ciò significa anche che il DTO non è necessario. Altrimenti, il tuo codice sembra che dovrebbe funzionare. Ecco il tuo codice originale nella sua interezza con le modifiche che ho menzionato:

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;
}

Per provare la mia teoria, ho riprodotto il comportamento nullo che stai riscontrando e poi ho apportato quella modifica. Si è bloccato per un po' (probabilmente per far scattare EF in marcia), ma poi è stato eseguito rapidamente ogni volta in seguito. In ogni caso, ho trovato un valore in attesa nel parametro out.

Se qualcuno là fuori sta incontrando problemi, c'è una variante a mano libera che si occupa dei dettagli di scripting per te:

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;
}

Come ripensamento, tecnicamente potresti utilizzare la tua soluzione originale se hai invocato la query subito dopo (ad esempio query.FirstOrDefault() ). Il valore di ritorno della query sarebbe sempre null, ma il tuo parametro out verrebbe almeno popolato. Questo perché le query EF utilizzano l'esecuzione posticipata.