我有以下存储过程:
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调用它?我试过了:
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执行相同的任务。
答案 0 :(得分:3)
你看起来很棒。如果您担心代码的详细程度,并且使用了许多存储过程,那么您可以使用此扩展方法来删除一些重复的代码:
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);
}
所以参数是:
存储过程名称即。 PRODUCT_DETAILS
可选输入参数的对象
,new { p_code = redemptionCode, other = "value" }
可选输出光标的名称 - 默认为cursorParam
注意:此代码未经测试,因为我没有Oracle安装程序,但它确实可以编译,并且希望能够在某种程度上简化存储过程。
答案 1 :(得分:2)
到目前为止,结果是以下代码:
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);
}
}
但我认为应该有更好的方法来做到这一点。
答案 2 :(得分:1)
晚会,但只需在声明中添加BEGIN
和END
就可以解决此问题......它会起作用。
在我的情况下,我试图刷新物化视图,只有在添加BEGIN后才能使用END,否则会抛出OracleException ORA-00900: invalid SQL statement...
这应该有效:
db.ExecuteSql("BEGIN DBMS_SNAPSHOT.REFRESH('" + materializedViewName + "'); END;");