2

我正在尝试使用 nHibernate 将存储过程的输出映射到我的项目中的对象。

该对象的定义如下:

public class NewContentSearchResult
{
    public string Name { get; set; }
    public string ContentType { get; set; }
    public int Count { get; set; }
    public int CMIId { get; set; }
    public int FeatureId { get; set; }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

映射如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Class.Assembly"
    namespace="Class.Assembly"
    default-lazy="false" default-cascade="none">
  <class name="NewContentSearchResult" mutable="false" check="none">
    <composite-id unsaved-value="none">
      <key-property name="CMIId" type="int" />
      <key-property name="FeatureId" type="int" />
    </composite-id>
    <property name="ContentType" type="string" />
    <property name="Name" type="string" />
    <property name="Count" type="int" />
  </class>
  <sql-query name="spWebGetNewContentBySalesRole">
    <return class="NewContentSearchResult" lock-mode="read">
      <return-property name="Name" column="Name" />
      <return-property name="ContentType" column="FeatureDesc" />
      <return-property name="Count" column="Number" />
      <return-property name="CMIId" column="CMIId" />
      <return-property name="FeatureId" column="FeatureId" />
    </return>
    exec core.spWebGetNewContentBySalesRole :SalesRoleId
  </sql-query>
</hibernate-mapping>

存储的 proc 调用是正确的,我得到的结果类似于 SalesRoleId 266(例如):

CMIId       FeatureDesc       FeatureId     Name       Count
4000719 Guest Book          12     Charlie Brown    2
4000719 Audio Guest Book    3      Charlie Brown    1

如果没有复合键(仅使用 CMIId),它工作得很好,除非有 2 个结果(如上)共享一个 CMIId ......第二个被第一个覆盖。

我必须使用复合键,CMIId/FeatureId 是逻辑组合。

当我现在运行它时,我得到一个异常:

NHibernate.ADOException: could not execute query
[ exec core.spWebGetNewContentBySalesRole ? ]
  Name: SalesRoleId - Value: 266
[SQL: exec core.spWebGetNewContentBySalesRole ?] --->  System.IndexOutOfRangeException: CMIId22_0_.
4

4 回答 4

5

好的,进一步的研究使我确信,当您使用存储过程时,nHibernate 中不可能有复合 id。

为此,我修改了我的 SQL 以包含 rownumber() 并将其用作 id。我只能这样做,因为它是只读的,没有写入数据库,但它适用于我的目的。

于 2009-07-08T16:23:40.567 回答
2

过去,当我使用复合键时,我总是必须为该 ID 创建一个单独的类,该类的属性与复合的单独键相匹配。你试过这个吗?

于 2009-07-08T15:59:01.940 回答
2

正如接受的答案中提到的,我最终通过使用 ROWNUM 函数在 Oracle 中使用了唯一的行号破解。后来,我在重用不同参数的查询时遇到了问题。似乎 nHibernate 记住了 id 并希望将它们与新返回的结果相关联,从而带回不正确的行。我通过将行号与时间戳相结合来解决此问题,如下所示:

(ROWNUM * 10000000000 + dbms_utility.get_time) AS ROW_ID

这样,您就可以保证每次都为您的查询结果获得全新的 id。只需确保使用足够大的整数来保存映射对象中的值。我ulong在 c#.net 中使用 8 个字节。您还可以从乘数中取出几个 0 以使 ID 更短。

于 2011-04-25T16:39:13.953 回答
1

有点晚了,但我可以第二马克 Struzinski - 这是可能的。

我最近遇到了这个问题,并通过对复合键使用单独的类并使用映射中的元素来解决它,如下所示。

<sql-query name="spWebGetNewContentBySalesRole" >
    <return class="NewContentSearchResult">
        <return-property name="NewContentSearchResultKey">
            <return-column name="CMIIdColumn" />
            <return-column name="FeatureIdColumn" />
        </return-property>
        <return-property name="Name" column="Name" />       
        <return-property name="ContentType" column="FeatureDesc" />       
        <return-property name="Count" column="Number" />       
    </return>
    exec core.spWebGetNewContentBySalesRole :SalesRoleId 
</sql-query>

请注意,return-column 元素中的“name”属性表示结果集中的名称,并且应该与 id 类中的属性的顺序相同。

于 2010-10-14T12:26:02.183 回答