Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Aufrufen einer gespeicherten Oracle-Prozedur mit Entity Framework mit Ausgabeparameter?

In diesem Fall sollten Sie nicht aufrufen:

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

Rufen Sie stattdessen Folgendes auf:

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

Beachten Sie, dass der einzige effektive Unterschied darin besteht, dass SqlQuery<CmdRegisterAssetDto> wurde durch ExecuteSqlCommand ersetzt . Dies bedeutet auch, dass der DTO unnötig ist. Ansonsten sieht Ihr Code so aus, als ob er funktionieren sollte. Hier ist Ihr ursprünglicher Code in seiner Gesamtheit mit den von mir erwähnten Änderungen:

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

Um meine Theorie zu beweisen, habe ich das Nullverhalten reproduziert, das Sie erleben, und dann diese eine Änderung vorgenommen. Es hing für eine Weile (wahrscheinlich, um EF in Gang zu bringen), wurde dann aber jedes Mal schnell ausgeführt. In jedem Fall habe ich einen Wert gefunden, der im out-Parameter wartet.

Wenn irgendjemand da draußen in Schwierigkeiten gerät, gibt es eine Langhand-Variante, die sich um die Skriptdetails für Sie kümmert:

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

Als nachträglicher Gedanke könnten Sie technisch mit Ihrer ursprünglichen Lösung fortfahren, wenn Sie die Abfrage unmittelbar danach aufrufen (d. h. query.FirstOrDefault()). ). Der Rückgabewert der Abfrage wäre immer null, aber Ihr out-Parameter würde zumindest gefüllt werden. Dies liegt daran, dass EF-Abfragen eine verzögerte Ausführung verwenden.