Can not execute stored procedure with nHibernate
Firstly, I'm sorry for asking this question AGAIN when there are several resources that (theoretically) explain it. I've listed the references I used at the bottom of this question, hopefully they will help someone else if nothing else.
I am trying to execute a simple stored proc on an oracle 11 database. My intent is to create a List{T} object from data returned via a SYS_REFCURSOR. I get this error message as soon as I try to to create an nhibernate session object: {"Errors in named queries: {GET_COLLATERAL}"}
Here is my mapping. The namespace, schema, assembly, query name are spelled correctly. The file is named GetCollateral.hbm.xml and is marked as an embedded resource.开发者_如何学C
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Poolman" namespace="Poolman.Entities" schema="poolman_own">
<sql-query name="GET_COLLATERAL" callable="true">
<return class="Poolman.Entities.IDNamePair">
<return-property name="ID" column="sort_order"></return-property>
<return-property name="Name" column="collateral"></return-property>
</return>
{GET_COLLATERAL(?)}
</sql-query>
</hibernate-mapping>
After quite a bit of troubleshooting I managed to get a session object to be created by removeing the return element from the mapping as shown below. Apparently there is something wrong with it but I don't know what.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Poolman" namespace="Poolman.Entities" schema="poolman_own">
<sql-query name="GET_COLLATERAL" callable="true">
{GET_COLLATERAL(?)}
</sql-query>
</hibernate-mapping>
I don't expect to get a result set back with no return mapping, but using the mapping above allows nhibernate to create its session obect and to try to execute the query. However, nHibernate cannot get it's parameters right. I get this error message:
{"Expected positional parameter count: 1, actual parameters: [] [{GET_COLLATERAL(?)}]"}
I've tried:
CALL GET_COLLATERAL()
BEGIN GET_COLLATERAL(); END;
The above wrapped in CDATA
Here is my stored proc:
create or replace
PROCEDURE GET_COLLATERAL(p_cursor OUT SYS_REFCURSOR)
IS
BEGIN
OPEN p_cursor for
SELECT collateral, sort_order
FROM
(
-- Long query omitted. The query executes when pasted into a command window.
) ORDER BY sort_order ;
END;
Here is my entity class. This class does not map to any one table but I tried to create a mapping for it anyhow.
namespace Poolman.Entities
{
public class IDNamePair
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
}
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping assembly="Poolman"
namespace="Poolman.Entities"
schema="poolman_own"
xmlns="urn:nhibernate-mapping-2.2">
<class name="IDNamePair" table="x">
<id></id>
<property name="ID" column="sort_order"/>
<property name="Name" column="collateral"/>
</class>
</hibernate-mapping>
Here is the code I'm using to call the query:
public List<Entities.IDNamePair> GetCollateral()
{
IQuery query = (IQuery)Session.GetNamedQuery("GET_COLLATERAL");
List<Entities.IDNamePair> list = new List<Entities.IDNamePair>();
System.Collections.IList result = query.List();
list = result.OfType<Entities.IDNamePair>().ToList();
return list;
}
I really appreciate any help with this. I'm stuck. Here are links to other resources I've found, none can help me however: Sorry stackoverflow only allows me to post two links:
Oracle stored procedures, SYS_REFCURSOR and NHibernate
http://www.techonthenet.com/oracle/questions/cursor1.php
Maybe two considerations could be done for this problem:
- First, the Stored Procedure which has no input parameters, does not require to be called with parameters, so as this questions comment says calling sp with out ref cursor call the SP in this way
{ call GET_COLLATERAL }
- Second, to use a "not mapped" class as result set, you should instruct nhibernate about that "not mapped" class, so try to add
<import class="FullClassName" rename="ClassNameMayBeRenamed"/>
at top of the mapping file
So this could be a mapping for this SP:
....
<import class="Poolman.Entities.IDNamePair" />
....
<sql-query name="GET_COLLATERAL" callable="true">
<return class="Poolman.Entities.IDNamePair">
<return-property name="ID" column="sort_order"></return-property>
<return-property name="Name" column="collateral"></return-property>
</return>
{ call GET_COLLATERAL}
</sql-query>
The calling code could be a simple code to call a SP through NHibernate.. I hope this could be your solution. Please let me know if I'm wrong
Regards
精彩评论