Oracle存储过程与ADO一起工作.. NET但是使用OrmLite会抛出异常

本文关键字:OrmLite 抛出异常 NET 存储过程 ADO 一起 工作 Oracle | 更新日期: 2023-09-27 18:06:06

我有一个下面的存储过程:

create or replace PROCEDURE PRODUCT_DETAILS(p_code IN VARCHAR2, 
                                            cursorParam OUT SYS_REFCURSOR)
IS
BEGIN
  OPEN cursorParam FOR
  select str_auth_code, str_name
  from strs
  where str_auth_code = p_code;
END;

如何用OrmLite调用它?我tryied:

connection.SqlList<Product>(@"EXEC PRODUCT_DETAILS @p_code", new { p_code = code });

但是会抛出异常ORA-01036: illegal variable name/number

我只是试着用普通的旧ADO来做。. NET和它工作:

using (var conn = new OracleConnection(connectionString))
{
    OracleCommand cmd = new OracleCommand();
    cmd.Connection = conn;
    cmd.CommandText = "PRODUCT_DETAILS";
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("p_code", OracleType.NVarChar).Value = redemptionCode;
    cmd.Parameters.Add("cursorParam", OracleType.Cursor);
    cmd.Parameters["cursorParam"].Direction = ParameterDirection.Output;
    conn.Open();
    OracleDataReader dr = cmd.ExecuteReader();
    while (dr.Read())
    {
        Console.WriteLine(dr["Name"]);
    }
    conn.Close();
}

但是我不知道如何用OrmLite做同样的任务

Oracle存储过程与ADO一起工作.. NET但是使用OrmLite会抛出异常

看起来不错。如果您担心代码的冗长性,并且正在使用许多存储过程,那么您可以使用这个扩展方法来删除一些重复的代码:

<标题>扩展方法:
public static class StoredProcExtensions
{
    public static List<T> ExecStoredProcedure<T>(this IDbConnection connection, string procedureName, object parameters = null, string outputCursor = "cursorParam")
    {
        return connection.Exec(c => {
            c.CommandText = procedureName;
            c.CommandType = CommandType.StoredProcedure;
            // Create the parameters from the parameters object
            if(parameters != null)
                foreach(var property in parameters.GetType().GetPublicProperties())
                    c.Parameters.Add(new OracleParameter(property.Name, property.GetValue(parameters)));
            // Add the output cursor
            if(outputCursor != null)
                c.Parameters.Add(new OracleParameter(outputCursor, OracleDbType.RefCursor) { Direction = ParameterDirection.Output });
            // Return the result list
            return c.ExecuteReader().ConvertToList<T>();
        });
    }
}

用法:

var download = connection.ExecStoredProcedure<ProductDownloads>(
                   "PRODUCT_DETAILS", 
                   new { p_code = redemptionCode }
               );
foreach (var productDownload in download)
{
    Console.WriteLine(productDownload.Name);
}

所以参数是:

  1. 存储过程名称PRODUCT_DETAILS

  2. 可选输入参数
    i的对象。e new { p_code = redemptionCode, other = "value" }

  3. 可选输出光标的名称—默认为cursorParam

注意:这段代码是未经测试的,因为我没有Oracle设置,但它可以编译,并有望在某种程度上简化您的存储过程

到目前为止,最后的代码如下:

using (var connection = factory.Open())
{
    var download = 
         connection.Exec(c =>
          {
               c.CommandText = "PRODUCT_DETAILS";
               c.CommandType = CommandType.StoredProcedure;
               c.Parameters.Add(
                  new Oracle.DataAccess.Client.OracleParameter("p_code", Oracle.DataAccess.Client.OracleDbType.NVarchar2) { Value = redemptionCode });
               c.Parameters.Add(
                   new Oracle.DataAccess.Client.OracleParameter("cursorParam", Oracle.DataAccess.Client.OracleDbType.RefCursor) { Direction = ParameterDirection.Output });
                return c.ExecuteReader().ConvertToList<ProductDownloads>();
           });
           foreach (var productDownload in download)
           {
               Console.WriteLine(productDownload.Name);
           }
}

但是我认为应该有更好的方法。

来得太晚了,但这个问题可以通过简单地将BEGINEND添加到语句中来解决…会成功的。

在我的情况下,我试图刷新一个物化视图,只有在添加BEGIN和END之后才会工作,否则它会抛出OracleException ORA-00900: invalid SQL statement...

这个应该可以工作:

db.ExecuteSql("BEGIN DBMS_SNAPSHOT.REFRESH('" + materializedViewName + "'); END;");