Nesse caso, você não deveria estar chamando:
var query = ctx.Database.SqlQuery<CmdRegisterAssetDto>(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);
Mas em vez disso, ligue:
var result = ctx.Database.ExecuteSqlCommand(sql, projectNameParam, countryCodeParam, locationParam, assetRegisteredParam);
Observe que a única diferença efetiva é que
SqlQuery<CmdRegisterAssetDto>
foi substituído por ExecuteSqlCommand
. Isso também significa que o DTO é desnecessário. Caso contrário, seu código parece que deve funcionar. Aqui está seu código original na íntegra com as alterações que mencionei: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;
}
Para provar minha teoria, reproduzi o comportamento nulo que você está experimentando e, em seguida, fiz essa alteração. Ele travou um pouco (provavelmente para deixar o EF entrar em ação), mas depois foi executado rapidamente todas as vezes. Em cada caso, encontrei um valor esperando no parâmetro out.
Se alguém estiver com problemas, há uma variação longa que cuida dos detalhes do script para você:
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;
}
Como uma reflexão tardia, você tecnicamente poderia seguir com sua solução original se invocasse a consulta imediatamente após (ou seja,
query.FirstOrDefault()
). O valor de retorno da consulta sempre seria nulo, mas seu parâmetro out seria pelo menos preenchido. Isso ocorre porque as consultas EF usam execução adiada.