使用PostgreSQL和NHibernate命名查询

时间:2015-01-28 20:38:21

标签: c# postgresql nhibernate named-query

我正在与NHibernate命名查询和PostgreSQL搏斗,但无法让它工作。我在PostgreSQL数据库中有一个函数:

create or replace function x(results refcursor, id_ bigint)
  returns refcursor
  as
  $$
begin
  open results for
select
    id,
    name,
    number
from
    table_name
where
    id = id_;

    return results;
end;
  $$ language plpgsql;

然后我在NHibernate中进行了映射:

<sql-query name="SqlQueryForTesting">
    <return-scalar column="id" type="long" />
    <return-scalar column="name" type="string" />
    <return-scalar column="number" type="string" />
    <![CDATA[
      begin;
      select x('table_name_cursor', :id);
      fetch all in table_name_cursor;
      commit;
    ]]>
  </sql-query>

最后制作了一个调用这个命名查询的方法。

public IList MethodForNamedQuery(int id)
        {
            var query = Session.GetNamedQuery("SqlQueryForTesting");
            query.SetInt32("id", id);
            return query.List();
        }

问题是这段代码给了我一个错误。

System.IndexOutOfRangeException
Field not found
   at Npgsql.NpgsqlRowDescription.FieldIndex(String fieldName)
   at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name)
   at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name)
   at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name, ISessionImplementor session, Object owner)
   at NHibernate.Loader.Custom.CustomLoader.ScalarResultColumnProcessor.Extract(Object[] data, IDataReader resultSet, ISessionImplementor session)
   at NHibernate.Loader.Custom.CustomLoader.ResultRowProcessor.BuildResultRow(Object[] data, IDataReader resultSet, Boolean hasTransformer, ISessionImplementor session)
   at NHibernate.Loader.Custom.CustomLoader.GetResultColumnOrRow(Object[] row, IResultTransformer resultTransformer, IDataReader rs, ISessionImplementor session)
   at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

NHibernate.Exceptions.GenericADOException
could not execute query
[ begin;
      select x('table_name_cursor', :p0);
      fetch all in table_name_cursor;
      commit; ]
  Name:id - Value:2

如果我通过pgAdmin运行我的查询,它可以完美地运行并返回一行。所以我猜这个问题在映射的某个地方。有人可以说我的映射有什么问题吗?

2 个答案:

答案 0 :(得分:0)

NHibernate不知道它是一个原生查询,因此它试图将其解释为常规NHibernate查询,它将通过映射实体进行搜索。

如果您可以将函数创建为存储过程,则可以定义命名查询,如this example

<sql-query name="selectAllEmployments_SP">
    <return alias="emp" class="Employment">
        <return-property name="employee" column="EMPLOYEE"/>
        <return-property name="employer" column="EMPLOYER"/>
        <return-property name="startDate" column="STARTDATE"/>
        <return-property name="endDate" column="ENDDATE"/>
        <return-property name="regionCode" column="REGIONCODE"/>
        <return-property name="id" column="EID"/>
        <return-property name="salary">
            <return-column name="VALUE"/>
            <return-column name="CURRENCY"/>
        </return-property>
    </return>
    exec selectAllEmployments
</sql-query>

答案 1 :(得分:0)

我猜id是一个输入参数,但在您的查询中,它使用return-scalar声明为输出参数。尝试将其更改为query-param,看看它是否有效:

<query-param column="id" type="long" />