简体   繁体   中英

Call an Oracle stored procedure using EF Core ExecuteSqlRaw

I have an Oracle stored procedure (in a package) with the following signature:

procedure My_StoredProcedure
                         (p_start_date IN DATE,
                          p_end_date IN DATE,
                          p_result_cursor OUT out_cursor,
                          p_message OUT VARCHAR2
                          );

Where out_cursor is defined in the package as type out_cursor is ref cursor;

As this is a stored procedure that aggregates 3 different tables I did not have a single entity generated (as database first) for the stored procedure results, after scaffolding using Entity Framework Core for Oracle.

The C# code for the method, which calls this stored procedure is:

var parameters = new[] {
            new OracleParameter("p_start_date", OracleDbType.Date, startDate, ParameterDirection.Input),
            new OracleParameter("p_end_date", OracleDbType.Date, endDate, ParameterDirection.Input),
            new OracleParameter("p_result_cursor", OracleDbType.RefCursor, ParameterDirection.Output),
            new OracleParameter("p_message", OracleDbType.Varchar2, ParameterDirection.Output)
        };
                                       
var sql = "BEGIN MY_PKG.My_StoredProcedure(:p_start_date, :p_end_date, :p_result_cursor, :p_message); END;";

int rowsAffected = _dbContext.Database.ExecuteSqlRaw(storedProc, parameters);

This is not working as I would expect, although the rowsAffected variable contains -1, and there is no error being returned, I see nothing being returned in the parameters[2] or parameters[3] of the parameters variable.

I suspect that the out_cursor definition may be tripping me up. I do not have control over the database or the creation of the stored procedure.

I am also open to a better way of doing this but any help would be gratefully received.

I have managed to resolve this issue myself by bringing together a few different strands to provide a complete solution.

Firstly, the use of the EF Core database first scaffolding to create the DbContext file & associated entities will NOT create the stored procedure as would be the case when using the EF wizard in the.Net Framework.

Therefore, once the scaffolding process is complete the entity model class, which will be used to stored the result from the store procedure needs to be created by hand and added to the DbContext generated file.

...
public virtual DbSet<SpResult> SpResults { get; set; } = null!;

Additionally, since the results will not have a primary key this also needs to be specified in the generated DbContext file, along with any handling for mapping column names to entity model properties or value conversions:

modelBuilder.Entity<TicketSale>(entity =>
{
   entity.HasNoKey();
    
   entity.Property(e => e.Price)
      .HasColumnName("PRIICE");
    
   entity.Property(e => e.Date)
      .HasConversion(val => val.ToShortDateString(), val => DateTime.Parse(val));

For the type out_cursor defined in the package, it is necessary to described this as a user defined type in the Oracle parameter property UdtTypeName , which is used by the stored procedure:

var parameters = new[] {
...,
new OracleParameter() 
    {
       ParameterName = "p_result_cursor",
       OracleDbType = OracleDbType.RefCursor,
       Direction = ParameterDirection.Output,
       UdtTypeName = "MY_PKG.out_cursor"
    },
...
};

Finally, the stored procedure can now be called as follows:

var storedProc = "BEGIN MY_PKG.My_StoredProcedure(:p_start_date, :p_end_date, :p_result_cursor, :p_message); END;";
return _dbContext.SpResults.FromSqlRaw(storedProc, parameters).ToList();

Additonally, it is possible to do this using the ExecuteSqlRaw via a OracleCommand , OracleDataAdapter , DataSet and selecting the contents of the DataTable with a LINQ expression and creating a list of the stored procedure result class, however when using EF Core I do think this is the tidier solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM