在实体框架中使用存储函数的用法

6
我有一个旧的Oracle数据库,我想在EntityFramework 4.1应用程序中使用它。我已经了解了Oracle与EF的重大限制,即除非您创建包装过程,否则无法使用EF调用Oracle存储的函数。我的数据库中有数千个存储的函数,是否有其他解决方法?比如使用原始的Context.SqlQuery()?到目前为止,我还没有找到解决方案...

Oracle文档:

Oracle开发人员可以通过实体框架(Entity Framework)的函数导入(Function Imports)和存储过程映射(stored procedure mappings)来使用PL/SQL存储过程,但有一些限制。函数导入用于显式调用存储过程,而存储过程映射则会在实体Insert、Update和Delete操作时自动调用。

只能调用Oracle存储过程,不能调用存储函数。 (如果存储函数被包装在一个使用OUT参数作为返回值的存储过程中,则可以使用该存储函数。)

1个回答

6
如果您正在使用Entity Framework 4.1 Code First,可以尝试使用 Database.SqlQuery方法。例如,对于此函数。
CREATE OR REPLACE FUNCTION USERNAME_CTX.FUNCTION1 (param number)
 RETURN number
AS
BEGIN
 return param + 1;
END;

你可以使用这段代码:

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

}

编辑:

请注意,这是针对dotConnect for Oracle的解决方案(也许对于实现类似解决方案的ODP.NET有用)

对于此函数:

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;

你可以使用以下代码:
   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);
      }

编辑2

或使用此代码:

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

+1 感谢,但如果函数有一个 OUT 参数,那么它将不起作用。 :( - gdoron
请注意,答案已经再次修改。 - Devart
Devart.Data.Oracle 命名空间位于哪里? - gdoron
正如我之前提到的,只有在使用dotConnect for Oracle提供程序时,您才能使用Devart.Data.Oracle命名空间。 - Devart
我们如何使用Entity Framework 6和Devart.Data.Oracle提供程序调用oracle package - Amir
Amir,请看一下这个链接https://dev59.com/KXzaa4cB1Zd3GeqPU9Wj - Devart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接