Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Wywołanie procedury składowanej Oracle przy użyciu Entity Framework z parametrem wyjściowym?

W takim przypadku nie powinieneś dzwonić:

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

Ale zamiast tego zadzwoń:

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

Zauważ, że jedyną efektywną różnicą jest to, że SqlQuery<CmdRegisterAssetDto> został zastąpiony przez ExecuteSqlCommand . Oznacza to również, że DTO jest niepotrzebne. W przeciwnym razie Twój kod wygląda na to, że powinien działać. Oto Twój oryginalny kod w całości ze zmianami, o których wspomniałem:

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

Aby udowodnić swoją teorię, odtworzyłem zerowe zachowanie, którego doświadczasz, a następnie wprowadziłem tę jedną zmianę. Zatrzymał się na chwilę (prawdopodobnie po to, by EF włączył się w bieg), ale potem wykonywał się szybko za każdym razem. W każdym przypadku znalazłem wartość oczekującą w parametrze out.

Jeśli ktoś ma kłopoty, istnieje odręczna odmiana, która zajmie się szczegółami skryptu za Ciebie:

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

Po namyśle, technicznie rzecz biorąc, możesz skorzystać z oryginalnego rozwiązania, jeśli wywołasz zapytanie natychmiast po nim (tj. query.FirstOrDefault() ). Wartość zwracana przez zapytanie zawsze będzie równa null, ale parametr out zostanie przynajmniej wypełniony. Dzieje się tak, ponieważ zapytania EF używają wykonania odroczonego.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tworzenie profili w Oracle dla bezpieczeństwa użytkownika

  2. Podzapytania i multitabele

  3. Produkt () funkcja agregująca

  4. Jak wygenerować całe DDL schematu Oracle (skryptowalne)?

  5. PLS-00382:wyrażenie jest niewłaściwego typu przez wykonanie funkcji i spróbuj umieścić typ powrotu w zmiennej