1

継承と NHibernate を使用してロール ベースの構造を設定するのに問題があります。

基本的には、ObjectInRole という抽象クラスが必要です。このクラス (および対応するデータベース テーブル) には、RoleId、ObjectId、および ObjectType (これが識別子列になります) が含まれます。識別子列は、ロールを取得するオブジェクト タイプになります。

簡単にするために、ロールのリスト (バッグ) を含むユーザー オブジェクトがあると仮定します。ObjectInRole のサブクラスとなる UserInRole クラスを持つことができるようにしたいと思います。

こんなバッグを作りました。

<bag name="Roles" table="ObjectInRole" where="ObjectType = 'AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core'" generic="true"
     access="field.pascalcase-underscore" lazy="true">
  <key column="ObjectId" />
  <many-to-many class="AthletesCafe.Core.Domain.System.Roles.Role, AthletesCafe.Core" column="RoleId" />
</bag>

ObjectInRole のマッピングを次のように設定しました。

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="AthletesCafe.Core.Domain.System.Roles" assembly="AthletesCafe.Core">
  <class name="ObjectInRole" table="ObjectInRole" lazy="true" abstract="true">
<id name="ID" type="Int32" unsaved-value="0">
  <column name="ID" not-null="true" unique="true" index="PK_ObjectInRole"/>
  <generator class="identity" />
</id>
<discriminator column="ObjectType" type="String" insert="true" force="true"/>
<property name="ApplicationName" column="ApplicationName" type="String" not-null="false" length="255" />
<property name="ObjectId" column="ObjectId" type="int" not-null="true" />
<property name="ObjectType" column="ObjectType" type="String" />

<many-to-one name="Role" column="RoleId" class="AthletesCafe.Core.Domain.System.Roles.Role, AthletesCafe.Core" not-null="true" cascade="none" />

<subclass name="AthletesCafe.Core.Domain.System.Roles.UserInRole" 
          discriminator-value="AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core">
  <many-to-one name="User" column="ObjectId" class="AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core" not-null="false" cascade="none" />
</subclass>

この設定を行って実行すると、User オブジェクトのコレクションに新しい Role を追加すると、ObjectType フィールドを保存できません。ObjectToRole テーブルに新しいエントリを保存しますが、ObjectType は null です。バッグを見ると、これはコレクションにロードされません。サブクラス構造が正しく設定されていないか、バッグが正しく設定されていないことに絞り込んだと思います。サブクラス UserInRole ではなく、コレクションを抽象クラスの束として扱っているだけかもしれないと思うので、私はバッグに傾いています。

いずれかの分野について、ご意見をお聞かせください。ありがとう!

編集:

そのため、バッグ (User.Roles.add(Role)) に追加して多対多でリンク オブジェクトを保持する代わりに、オブジェクトをテーブルに直接追加することにしました。新しいエラーが表示されます:

null id in AthletesCafe.Core.Domain.System.Roles.UserInRole entry (don't flush the Session after an exception occurs) 

上記のクラスを見ると、User オブジェクトと Role オブジェクトが設定されています。id は ID フィールドであり、そのように指定されます。私は完全に途方に暮れています。

4

1 に答える 1

2

わかった!マッピング ファイルをいじってみたところ、文書化されていない問題が見つかりました (少なくとも、私が犯したエラーについての言及は見つかりませんでした)。

サブクラス化を使用する場合、親クラスには識別子列であるプロパティのマッピングを含めることはできません。私が投稿した 2 番目のマッピング ドキュメントを見ると、スーパー クラスとサブ クラスが示されています。スーパー クラスの識別子は ObjectType 列です。また、これをプロパティとして抽象クラス ObjectInRole にマップします。これはできません。この行が削除されると、すべてが正しく機能しました (バッグは保存されません)。

バッグは、ドキュメントで見つけたものでは制御できない問題のようです。マッピングによって抽象クラスが保存されている場所の別のインスタンスが見つかりません。NHibernate は、リンク クラスが UserInRole オブジェクトであり、ObjectInRole オブジェクトではないことを認識していないようです。バッグ ノードに提供されているすべてのオプションを調べたところ、多対多の関連付けを行うためにリンクしているクラスのタイプを NHibernate に伝える明らかな方法はありませんでした。私が言えることから、それは気にしませんが、多かれ少なかれ、テーブルをマップされたオブジェクトではなく、単なるテーブルとして扱います。挿入に何かを追加するように指示する方法があれば、それは可能かもしれませんが、これに関する情報は見たことがありません。

于 2009-03-21T01:07:55.423 に答える