Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usage of stored functions in entity framework

I have an old Oracle DB which I'm trying to use within EntityFramework 4.1 application.
I've read about the big limitation that oracle has with EF- you can't call Oracle stored Function with EF unless you create a wrapping Procedure.

I got thousands of stored functions in my DB, is there any other way to solve it?
Like using raw Context.SqlQuery()?

So far I couldn't find a solution for it...


Oracle docs:

Oracle developers can leverage PL/SQL stored procedures, with limitations, within the entity framework via Entity Framework Function Imports (used to call the procedures explicitly) and stored procedure mappings (which are automatically called for entity Insert, Update, and Delete operations).

Only Oracle stored procedures can be called by Entity Framework, not stored functions. (Oracle stored functions can be used if they are wrapped inside of a stored procedure that uses an OUT parameter for the stored function return value.)

like image 585
gdoron is supporting Monica Avatar asked Oct 09 '12 11:10

gdoron is supporting Monica


People also ask

What are the advantages of stored functions?

Executable code is automatically cached and shared among users. This lowers memory requirements and invocation overhead. By grouping SQL statements, a stored procedure allows them to be executed with a single call. This minimizes the use of slow networks, reduces network traffic, and improves round-trip response time.

Can we use stored procedure in Entity Framework?

You can use stored procedures either to get the data or to add/update/delete the records for one or multiple database tables. EF API creates a function instead of an entity in EDM for each stored procedure and User-Defined Function (UDF) in the target database.

Why we use function and stored procedure?

In a function, it is mandatory to use the RETURNS and RETURN arguments, whereas in a stored procedure is not necessary. In few words, a stored procedure is more flexible to write any code that you want, while functions have a rigid structure and functionality.

Can we use stored procedure in Entity Framework Core?

You can execute SP using FromSql method in EF Core in the same way as above, as shown below.


1 Answers

If you are working with Entity Framework 4.1 Code First, you can try using the Database.SqlQuery Method . For example, for this function

CREATE OR REPLACE FUNCTION USERNAME_CTX.FUNCTION1 (param number)
 RETURN number
AS
BEGIN
 return param + 1;
END;

you can use this code:

using (var ctx = new Model()) {
   var result =  ctx.Database.SqlQuery<int>("select username_ctx.FUNCTION1(:p0) from dual",1).FirstOrDefault();

}

EDITED:

Please note this solution for dotConnect for Oracle (maybe it will be useful for implementing a similar solution for ODP.NET)

For this function:

CREATE OR REPLACE FUNCTION USERNAME_CTX.FUNCTION2 (param number, int_param out number, str_param out varchar2)
  RETURN number
AS
BEGIN
   int_param := param + 2;
   str_param := 'value';
   return param + 1;
END;

You can use the following code:

   using (var ctx = new Model()) {
       var firstParam = new Devart.Data.Oracle.OracleParameter("p0", OracleDbType.Number, 1, ParameterDirection.Input);
       var secondParam = new Devart.Data.Oracle.OracleParameter("p1", OracleDbType.Number, ParameterDirection.Output);
       var thirdParam = new Devart.Data.Oracle.OracleParameter("p2", OracleDbType.VarChar, ParameterDirection.Output);
       var cursorParam = new Devart.Data.Oracle.OracleParameter("cursor_param", OracleDbType.Cursor, ParameterDirection.Output);

       var result = ctx.Database.SqlQuery<int>(
        @"declare
             res number;  
        begin
             res := username_ctx.FUNCTION2(:p0, :p1, :p2);
             open :cursor_param for select res from dual;
        end;",  firstParam, secondParam, thirdParam, cursorParam).FirstOrDefault();

       Console.WriteLine("Return value: {0}; int_param: {1}; str_param: '{2}'", result, secondParam.Value, thirdParam.Value);
      }

EDITED 2

or use this code:

     using (var ctx = new Model()) {
       var firstParam = new Devart.Data.Oracle.OracleParameter("p0", OracleDbType.Number, 1, ParameterDirection.Input);
       var secondParam = new Devart.Data.Oracle.OracleParameter("p1", OracleDbType.Number, ParameterDirection.Output);
       var thirdParam = new Devart.Data.Oracle.OracleParameter("p2", OracleDbType.VarChar, ParameterDirection.Output);
       var resultParam = new Devart.Data.Oracle.OracleParameter("res", OracleDbType.Number, 1, ParameterDirection.Output);
       ctx.Database.ExecuteSqlCommand(@"begin  :res := username_ctx.FUNCTION2(:p0, :p1, :p2);  end;", firstParam, secondParam, thirdParam, resultParam);
       Console.WriteLine("Return value: {0}; int_param: {1}; str_param: '{2}'", resultParam.Value, secondParam.Value, thirdParam.Value);
 } 
like image 70
Devart Avatar answered Sep 28 '22 05:09

Devart