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>

ストアド プロシージャの呼び出しは正しく、SalesRoleId 266 に対して次のような結果が返されます (例として)。

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

複合キーがなくても (CMIId のみを使用)、CMIId を共有する 2 つの結果 (上記のように) がある場合を除いて、正常に機能します... 2 番目は最初の結果によって上書きされます。

複合キーを使用する必要があり、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

OK、さらに調査した結果、ストアド プロシージャを使用する場合、nHibernate で複合 ID を使用することはできないことがわかりました。

そのために、SQL を変更して rownumber() を含め、それを ID として使用しています。これは読み取り専用であり、データベースへの書き込みがないため、これしかできませんが、私の目的には適しています。

于 2009-07-08T16:23:40.567 に答える
2

受け入れられた回答で述べたように、ROWNUM関数を使用してOracleで一意の行番号ハックを使用することになりました。その後、別のパラメーターを使用してクエリを再利用するときに問題が発生しました。nHibernate は ID を記憶していて、それらを新しく返された結果に関連付けようとしたため、誤った行が返されたようです。行番号とタイムスタンプを次のように組み合わせて、これを修正しました。

(ROWNUM * 10000000000 + dbms_utility.get_time) AS ROW_ID

このようにして、クエリの結果に対して毎回完全に新しい ID を取得することが保証されます。マップされたオブジェクトに値を保持するのに十分な大きさの整数を使用していることを確認してください。私ulongは8バイトのc#.netでaを使用しています。ID を短くするために、乗数からいくつかの 0 を取り出すこともできます。

于 2011-04-25T16:39:13.953 に答える
2

過去に複合キーを使用したときは、複合の個別のキーと一致するクラスのプロパティを使用して、その ID 用に個別のクラスを作成する必要がありました。これを試しましたか?

于 2009-07-08T15:59:01.940 に答える
1

少し遅れましたが、Mark 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 に答える