I am using Entity Framework with Oracle in a project and trying to call a stored procedure from EF. The procedure goes as
Create or Replace Procedure usp_RotaPlateProductie_Select(
p_afdelingId in varchar2,
p_productTypeId in varchar2,
p_productieData out sys_refcursor)
IS
Begin
Open p_productieData for
Select rp.Batchnummer, cppo.Productnummer, p.Omschrijving, pra.Bruto_In_Meters
From Rotaplateproductie rp inner join Productieresultaatrtplrol pra
on rp.Batchnummer = pra.Batchnummer inner join Cpiplusproductieorder cppo
on pra.ProductieNummer = cppo.ProductNummer inner join Product p
on cppo.Productnummer = p.Productnummer Where rp.Afdelingid = p_afdelingId
and rp.producttype = p_productTypeId;
END;
But when EF executes the function I am getting the error below
ORA-06550: line 1, column 8:
PLS-00306: wrong number or types of arguments in call to 'USP_ROTAPLATEPRODUCTIE_SELECT.
ORA-06550: line 1, column 8:
PL / SQL: Statement IGNORED.
I am calling this procedure using the below code
public ObjectResult<RotaPlateProductie> Search_RotaPlateProductie(global::System.String p_AFDELINGID, global::System.String p_PRODUCTTYPEID)
{
ObjectParameter p_AFDELINGIDParameter;
if (p_AFDELINGID != null)
{
p_AFDELINGIDParameter = new ObjectParameter("P_AFDELINGID", p_AFDELINGID);
}
else
{
p_AFDELINGIDParameter = new ObjectParameter("P_AFDELINGID", typeof(global::System.String));
}
ObjectParameter p_PRODUCTTYPEIDParameter;
if (p_PRODUCTTYPEID != null)
{
p_PRODUCTTYPEIDParameter = new ObjectParameter("P_PRODUCTTYPEID", p_PRODUCTTYPEID);
}
else
{
p_PRODUCTTYPEIDParameter = new ObjectParameter("P_PRODUCTTYPEID", typeof(global::System.String));
}
return base.ExecuteFunction<RotaPlateProductie>("Search_RotaPlateProductie", p_AFDELINGIDParameter, p_PRODUCTTYPEIDParameter);
}
Here RotaPlateProductie is the entity from which I am binding the result set
Please help.
You must add configuration;iIn your case should be as follows:
<oracle.dataaccess.client
<settings>
<add name="rp.usp_RotaPlateProductie_Select.RefCursor.p_productieData" value="implicitRefCursor bindinfo='mode=Output'" />...
<settings>
</oracle.dataaccess.client
Related
I'm trying to call an oracle stored function using eclipselink 2.6.5, the storedfunction has an oracle type input.
This is te stored func:
create or replace function TEST_FUNC(PAR1 IN VARCHAR2, PAR2 IN MY_TYPE_T)
return varchar2 is
begin
if PAR2 is null then
return (PAR1 || ' 0');
else
return(PAR1 || ' ' || PAR2.count);
end if;
end TEST_FUNC;
This is type declaration:
CREATE OR REPLACE MY_TYPE_T as table of MY_TYPE_R
CREATE OR REPLACE TYPE MY_TYPE_R as object
(
COD_P VARCHAR2(3),
COD_S VARCHAR2(10)
)
This is the type mapping:
#Embeddable
#Struct(name="MY_TYPE_R", fields= {"COD_P", "COD_S"})
#PLSQLTable(
name="MY_TYPE_R",
compatibleType="MY_TYPE_T",
nestedType="MY_TYPE_R"
)
public class MyRecordType {
#Column(name="COD_P")
private String codP;
#Column(name="COD_S")
private String codS;
//costructors, getter and setter...
}
This is the stored mapping:
#NamedPLSQLStoredFunctionQuery(
name="testFunc",
functionName="TEST_FUNC",
returnParameter=#PLSQLParameter(
name="RESULT",
databaseType = "VARCHAR_TYPE"),
parameters = {
#PLSQLParameter(name = "firstParam", queryParameter="PAR1", databaseType = "VARCHAR_TYPE"),
#PLSQLParameter(name = "secondParam", queryParameter="PAR2", databaseType = "MY_TYPE_T"),
}
)
This is the call:
#Test
public void testFuncTest() {
List<MyRecordType> recTypeList = new ArrayList<MyRecordType>();
MyRecordType rec = new MyRecordType();
rec.setCodP("PValue");
rec.setCodS("SValue");
recTypeList.add(rec);
Query query = getEM().createNamedQuery("testFunc");
query.setParameter("firstParam", "FOO");
query.setParameter("secondParam", recTypeList);
Assert.assertEquals("FOO 1", query.getSingleResult());
}
When I execute the test I get:
PLS-00306: wrong number or types of arguments in call to 'TEST_FUNC'
Actually reading the documentation on #PLSQTable I'm a bit confused on the tree parameters:
name
compatibleType
nestedType
Anyone has some suggestion?
First you'll want to use the OracleObject annotation to define your fields into an Oracle object. It's somewhat duplicate to Struct but required anyways.
#OracleObject(
name = "MY_TYPE_R"
, javaType = MyRecordType.class
, fields = {
#PLSQLParameter(name = "COD_P")
,#PLSQLParameter(name = "COD_S")
}
)
For the PLSQLTable you want
#NamedPLSQLStoredFunctionQuery(
name="testFunc",
functionName="TEST_FUNC",
returnParameter=#PLSQLParameter(
name="RESULT",
databaseType = "VARCHAR_TYPE"),
parameters = {
#PLSQLParameter(name = "PAR1", queryParameter="PAR1", databaseType = "VARCHAR_TYPE"),
#PLSQLParameter(name = "PAR2", queryParameter="PAR2", databaseType = "MY_TYPE_T"),
}
)
so the name needs to match what's in your function. The PLSQL table piece looks right, I believe the OracleObject part was your missing component and causing your error.
I have a procedure that takes in one VARCHAR parameter and returns an OUT CURSOR which is a list, in this case 3 rows with 9 columns.
My current JDBC Request:
CALL foo.bar.procedure('123456', ?)
Query type: Callable Statement
Parameter values: OUT
Parameter types: OUT -10
Variable names: outList
Result variable name: resultList (this is always null, does it mean that the result is empty?)
Handle ResultSet: Store as Object
Response data:
-1 updates.
Output variables by position:
[1] oracle.jdbc.driver.OracleResultSetImpl#21512d0b
outList is now oracle.jdbc.driver.OracleResultSetImpl#21512d0b
I've tried getting some information from outList in a BeanShell sampler like is suggested here but I haven't been able to get anything from it except just the ResultSet object id.
I'm new to calling procedures through Jmeter, View Result Tree doesn't seem to show me any result data and I've been going back and forth with the SQL Query and the parameter values, trying to fix it, but I always have the same trouble with the output.
I've also tried something like this with similar settings:
DECLARE
refCursor sys_refcursor;
Type MyRec Is Record (
v1 varchar2(
v2 varchar2(50),
...
v13 varchar2(10));
rec MyRec;
BEGIN
foo.bar.procedure('123456',refCursor);
LOOP
FETCH refCursor INTO rec;
EXIT WHEN refCursor%NOTFOUND;
dbms_output.put_line(
rec.v1||','||
rec.v2||','||
...
rec.v13);
END LOOP;
END;
Am I calling the procedure correctly or is something missing in the JDBC Request settings?
I finally solved this by moving away from JDBC Request sampler and used the BeanShell Sampler instead.
import java.sql.*;
import oracle.jdbc.*;
import org.apache.jmeter.protocol.jdbc.config.DataSourceElement;
ResultSet rs = null;
ResultSetMetaData rsmd = null;
CallableStatement stmt;
// "myConnConfigName" is the 'JDBC Connection Configuration' variable name
Connection conn = DataSourceElement.getConnection("myConnConfigName");
try {
stmt = conn.prepareCall("CALL foo.bar.procedure(?,?)");
stmt.setString(1, "123456");
stmt.registerOutParameter(2, OracleTypes.CURSOR);
stmt.executeUpdate();
rs = (ResultSet) stmt.getObject(2);
while (rs.next()) {
rsmd = rs.getMetaData();
log.info("ColumnCount:" + rsmd.getColumnCount().toString());
log.info("RowNo:" + rs.getRow().toString());
// TODO: Store data.
// Loop through columns with rs.getString(i);
}
}
catch(Throwable ex) {
log.error("Error message: ", ex);
throw ex;
}
finally {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
Add JSR223 PostProcessor as a child of your request
Extract the "interesting" values from the OracleResultSetImpl as per Retrieving and Modifying Values from Result Sets article, something like:
import java.sql.ResultSet
ResultSet rs = (ResultSet)vars.getObject('outList')
while (rs.next()) {
vars.put('column_1_row_1_value`, rs.getString(0))
///...
}
See JDBC Tutorial and Apache Groovy - Why and How You Should Use It for more details.
Hi I am using spring jdbctemplate to invoke an oracle function which takes an integer input.
Oracle function is :
FUNCTION get_key_types (type_id IN integer)
RETURN tcur_key_types_det
IS
lv_cur tcur_key_types_det;
BEGIN
IF type_id IS NULL
THEN
RAISE KEY_ERROR;
ELSE
OPEN lv_cur FOR
SELECT key_criteria_cd,
key_type_name,
KEY_COLUMN_TXT,
data_type_cd
FROM key_criteria
WHERE criteria_type_id = type_id
ORDER BY key_type_name;
END IF;
RETURN lv_cur;
END get_key_types;
I have a Java class that extends from Class StoredProcedure which passes and integer argument to invoke the oracle function as follows.
public class KeyTypeService extends StoredProcedure{
public KeyTypeService(DataSource dataSource,String sqlString) {
setDataSource(dataSource);
setFunction(true);
setSql(sqlString);
declareParameter(new SqlParameter("type_id",Types.INTEGER));
declareParameter(new SqlOutParameter("functionName",OracleTypes.CURSOR,new KeyTypeMapper()));
compile();
}
public Map execute(int category_id) {
Map<String, Object> inputs = new HashMap<String, Object>();
inputs.put("type_id", category_id);
Map output = execute(inputs);
return output;
}
}
I invoke the oracle function as follows.
int i = 60;
KeyTypeService keyTypeService = new KeyTypeService((DataSource)c.getBean ("DataSource"),"get_key_types");
map = keyTypeService.execute(i);
I get the following error indicating that I am not passing the correct data type expected.
PLS-00306: wrong number or types of arguments in call to 'get_key_types'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
Any help would be highly appreciated..
Since my comment was correct:
The out parameter must come first.
Spring documentation might not explicitly talk about the order but the parameter order must be the same order as when you would call a pl/sql function without spring. I.e.:
out = call pacakge.function(in)
I use three table for a section of my program :
1- aspnet_membership (Fields of table are in asp.net membership )
2-aspnet_user (Fields of table are in asp.net membership )
3-TBL_INFO (Filds : INFO_ID,INFO_USERNAME,INFO_ADDRESS,INFO_TELL)
So,When I want show the required field in Gridview , everything is ok and I don't have any problem .
Store Procedure for SELECT :
CREATE PROCEDURE STR_SELECT_USERS_ADMIN
AS
SELECT aspnet_Users.UserId, aspnet_Users.UserName, aspnet_Membership.CreateDate, TB_INFO.INFO_ADDRESS, TB_INFO.INFO_TELL, aspnet_Membership.Email,
aspnet_Membership.LastLoginDate
FROM aspnet_Membership INNER JOIN
aspnet_Users ON aspnet_Membership.UserId = aspnet_Users.UserId INNER JOIN
TB_INFO ON aspnet_Users.UserName = TB_INFO.INFO_USERNAME
But when i decide to delete a user , I can't :
Stored Procedure for Delete :
ALTER PROCEDURE STR_DELETE_USER
(
#UserId UNIQUEIDENTIFIER
)
AS
DELETE FROM aspnet_Users
WHERE (UserId = #UserId)
and my code in Program for delete in GridView is as Below :
protected void GridView1_SelectedIndexChanged1(object sender, EventArgs e)
{
string strUserName = GridView1.Rows[GridView1.SelectedIndex].Cells[0].Text;
if (Membership.DeleteUser(strUserName, true) == true)
{
//GridView1.DataBind();
lblResult.Text = "Delete Successfully";
}
else
{
lblResult.Text = "Delete Faild";
}
GridView1.DataBind();
}
and The error when i'm going delete a record create as below :
Server Error in '/' Application.
--------------------------------------------------------------------------------
The parameter 'username' must not be empty.
Parameter name: username
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: The parameter 'username' must not be empty.
Parameter name: username
Source Error:
Line 26: string strUserName = GridView1.Rows[GridView1.SelectedIndex].Cells[0].Text;
Line 27:
Line 28: if (Membership.DeleteUser(strUserName, true) == true)
Line 29: {
Line 30: //GridView1.DataBind();
Thank You For Your Time. Thank You So Much
I am trying to call a function (oracle) using nhibernate that return ref cursor, but i am not successful with the hbm file, can any one please guide me with this.
If i make it like <return class ... I am getting configuration error.
I tried { ? = call package.function(:a, :b, :c) as result from dual }, even this is also not working.
There are some limitations when calling ORACLE functions/procedures with nHibernate.
As stated in the reference documentation (17.2.2.1):
For Oracle the following rules apply:
A function must return a result set. The first parameter of a
procedure must be an OUT that returns a result set. This is done by
using a SYS_REFCURSOR type in Oracle 9 or 10. In Oracle you need to
define a REF CURSOR type, see Oracle literature.
I've tried to play a little bit with it as I am having the same problem.
Here is the PACKAGE-PROCEDURE:
HEAD:
create or replace
PACKAGE "MYPACKAGE" AS
TYPE ReferenceCursor IS REF CURSOR;
PROCEDURE usp_GetDual
(
pCursor OUT ReferenceCursor,
a IN CHAR,
b IN CHAR
);
END MYPACKAGE;
BODY:
PROCEDURE usp_GetDual
(
pCursor OUT ReferenceCursor,
a IN CHAR,
b IN CHAR
)
IS
err_code NUMBER;
err_msg VARCHAR2(200);
BEGIN
OPEN pCursor FOR
SELECT * FROM dual;
EXCEPTION
WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := substr(SQLERRM, 1, 200);
END usp_GetDual;
This my mapping file:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly">
<sql-query name="GetDaul">
{ call MYPACKAGE.usp_GetDual ( :a, :b ) }
</sql-query>
</hibernate-mapping>
and this is the code I've used to test it:
var value = Session.GetNamedQuery("GetDaul")
.SetParameter<string>("a", "AAA")
.SetParameter<string>("b", "BBB")
.UniqueResult();
As you can see the REF CURSOR must be the first parameter in your procedure (pCursor OUT ReferenceCursor) and you do not need to reference it in your mapping or your call.
If you want to return entities, things get a little bit more complicated.
Your mapping file must specify the return type (class):
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly">
<sql-query name="GetOrders">
<return class="MyAssembly.Domain.MyOrder, MyAssembly" />
{ call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) }
</sql-query>
</hibernate-mapping>
You have to define your entity:
public class MyOrder
{
public virtual string Number { get; set; }
public virtual int Ver { get; private set; }
public virtual string Company { get; set; }
public virtual string Customer { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
Order order = obj as Order;
if (order == null)
return false;
if (this.Number.Trim() == order.Number.Trim() &&
this.Ver == order.Ver &&
this.Company.Trim() == order.Company.Trim()
)
return true;
else
return false;
}
public override int GetHashCode()
{
int hash = 0;
hash = hash +
(null == this.Number ? 0 : this.Number.GetHashCode())
+
(this.Ver.GetHashCode())
+
(null == this.Company ? 0 : this.Company.GetHashCode());
return (hash);
}
}
and this is the mapping file for your entity:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="MyAssembly.Domain">
<class name="MyOrder" table="OCSAORH" mutable="false">
<composite-id>
<key-property name="Number" column="OCHORDN" type="String" length="10"></key-property>
<key-property name="Ver" column="OCHAMND" type="Int32"></key-property>
<key-property name="Company" column="OCHCOSC" type="String" length="5"></key-property>
</composite-id>
<property name="Customer" column="OCHCLII" type="String"></property>
</class>
</hibernate-mapping>
This is my ORACLE package:
PROCEDURE usp_GetOrders
(
pCursor OUT ReferenceCursor,
pCompanyCode IN CHAR,
pOrderNumer IN CHAR
)
IS
err_code NUMBER;
err_msg VARCHAR2(200);
BEGIN
OPEN pCursor FOR
SELECT
OCSAORH.*
FROM OCSAORH
WHERE OCSAORH.OCHAMND = 0
AND OCSAORH.OCHCOSC = pCompanyCode
AND OCSAORH.OCHORDN = pOrderNumer;
EXCEPTION
WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := substr(SQLERRM, 1, 200);
END usp_GetOrders;
And now you can easily get your orders using parameters:
var listOfOrders = Session.GetNamedQuery("GetOrder")
.SetParameter<string>("pCompanyCode", "ABC")
.SetParameter<string>("pOrderNumer", "XYZ")
.List<Domain.MyOrder>();
This article helped me to understand how thing must be done.
I solve it basing on this post mapping-to-oracle-stored-procedure-with-fluent-nhibernate
Here is my summary:
In the procedure you have to declare a first parameter of type OUT SYS_REFCURSOR. ex: p_cursor OUT SYS_REFCURSOR, MyVar1 int, MyVar2 nvarchar
To return the resulset do
OPEN p_cursor FOR <select statement here>;
in my case was a dynamic query and it works like a charm.
In the hbm mapping surround the call between
{ }
ex:
{ call MyProc (MyVar1, MyVar2) }
If you do not use the { }, nhibernate throws exception of "incorrect number of arguments".
I hope this helps someone.
I got the same trouble. I solved it by this:
Oracle PL/SQL in MyPackage:
...
function MyFunction(a number) return number is
n number;
pragma autonomous_transaction; -- Important!
begin
n:=apps.fnd_request.submit_request( ... );
commit; -- Important!
return n;
end;
mapping.hbm.xml: (Embedded Resource)
...
<sql-query name='MyFunctionQuery'>
<query-param name='par' type='System.Int64'/>
<return-scalar column='ret' type='System.Int64'/>
<![CDATA[
select MyPackage.MyFunction(:par) as ret from dual
]]>
</sql-query>
C#>
...
IQuery Q = session.GetNamedQuery("MyFunctionQuery")
.SetParameter("par", 1);
var result = Q.UniqueResult();
Best regards.
With the same thing on my side and on Oracle, NHibernate seems to loose the name of the procedure inside the package. So let's suppose the example upfront: call MYPACKAGE.usp_GetOrders ( :pCompanyCode , :pOrderNumer ) --> result that the package MyPackage is not a stored procedure.
WARN: Oracle.DataAccess.Client.OracleException ORA-06550: line 1, column 7: PLS-00221: 'MYPACKAGE' is not a procedure or is undefined ORA-06550: line 1, column 7: