[英]Oracle stored procedure works with ADO.NET but with OrmLite throws exception?
I have a following stored procedure: 我有以下存储过程:
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;
How can I call it with OrmLite? 如何用OrmLite来称呼它? I've tryied:
我试过了:
connection.SqlList<Product>(@"EXEC PRODUCT_DETAILS @p_code", new { p_code = code });
but it throws an exception ORA-01036: illegal variable name/number
但它引发异常
ORA-01036: illegal variable name/number
I just tried to do it with plain old ADO.NET and it worked: 我只是尝试使用普通的旧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();
}
But I can't figure out how to do the same task with OrmLite. 但我不知道如何使用OrmLite执行相同的任务。
What you have looks good. 你所拥有的看起来不错。 If you were concerned about the verbosity of the code, and were using a number of stored procedures, then you could use this extension method to remove some of the repeated code:
如果您担心代码的冗长性,并且正在使用许多存储过程,则可以使用此扩展方法删除一些重复的代码:
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);
}
So the arguments are: 因此参数为:
Stored procedure name ie PRODUCT_DETAILS
存储过程名称, 即
PRODUCT_DETAILS
Optional An object of input parameters 可选输入参数的对象
ie new { p_code = redemptionCode, other = "value" }
即
new { p_code = redemptionCode, other = "value" }
Optional The name of the output cursor - defaults to cursorParam
可选输出游标的名称-默认为
cursorParam
Note: this code is untested, because I don't have Oracle setup, but it does compile, and hopefully goes some way to simplifying your stored procedures. 注意:此代码未经测试,因为我没有安装Oracle,但确实可以编译,因此希望可以通过某种方式简化存储过程。
So far ended up with following code: 到目前为止,结果如下:
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);
}
}
But I think there should be a better way for doing this. 但是我认为应该有一个更好的方法。
Late to the party, but this problem can be solved by simply adding BEGIN
and END
to the statement... it will work. 聚会晚了,但是可以通过在语句中添加
BEGIN
和END
来解决此问题……它将起作用。
In my case, I was trying to refresh a materialized view, only after adding BEGIN and END will it work, otherwise it will throw OracleException ORA-00900: invalid SQL statement...
就我而言,我试图刷新实例化视图,只有在添加BEGIN和END之后它才能起作用,否则它将抛出
OracleException ORA-00900: invalid SQL statement...
This should work: 这应该工作:
db.ExecuteSql("BEGIN DBMS_SNAPSHOT.REFRESH('" + materializedViewName + "'); END;");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.