14

できる限り単純化しようとしたシステムのシナリオがあります。アーティファクト (と呼びましょう) のテーブルがあり、アーティファクトには任意の数のセキュリティ ロールがアクセスでき、セキュリティ ロールは任意の数のアーティファクトにアクセスできます。そのため、データベースには 3 つのテーブルがあります。1 つはアーティファクトを記述し、もう 1 つはロールを記述し、アーティファクト ID をロール ID にリンクする多対多の関連付けテーブルです。

ドメインに関しては、ロール用とアーティファクト用の 2 つのクラスがあります。アーティファクト クラスには、それにアクセスできるロールのリストを返す IList プロパティがあります。(ただし、ロールは、アクセス可能なアーティファクトを取得するためのプロパティを提供しません)。

そのため、artefact の nhibernate マッピングには以下が含まれます。

<bag name="AccessRoles" table="ArtefactAccess" order-by="RoleID" 
    lazy="true" access="field.camelcase-underscore" optimistic-lock="false">
    <key column="ArtefactID"/>
    <many-to-many class="Role" column="RoleID"/>
</bag>

これはすべて正常に機能し、アーティファクトを削除すると、関連付けテーブルが適切にクリーンアップされ、削除されたアーティファクトとロールの間のすべての参照が削除されます (ロールは正しく削除されませんが、孤児を削除したくないため)。

問題は、ロールを削除して関連付けテーブルを自動的にクリアする方法です。現在ロールを削除しようとすると、ロールの関連付けテーブルにまだエントリがあるため、参照制約が発生します。ロールを正常に削除する唯一の方法は、そのロールにリンクしているすべてのアーティファクトを照会し、アーティファクトのロール コレクションからロールを削除し、アーティファクトを更新してからロールを削除することです。簡素化されたシステムで、ロールは他のテーブル/オブジェクトにいくつでも関連付けることができます。

ロールを削除するたびに、この関連付けテーブルをクリアしたいことを NHibernate に示唆できるようにする必要があります。これは可能ですか。

助けてくれてありがとう。

4

5 に答える 5

8

私はこの答えを探していて、グーグルでこのスレッドを見つけたので(答えなしで)、これに私の解決策を投稿すると思いました。3 つのテーブル: Role、RolesToAccess(ManyToMany)、Access。

次のマッピングを作成します: アクセス:

<bag name="Roles" table="RolesToAccess" cascade="none" lazy="false">
      <key column="AccessId" />
      <many-to-many column="AccessId" class="Domain.Compound,Domain" />
    </bag>

<bag name="RolesToAccess" cascade="save-update" inverse="true" lazy="false">
      <key column="AccessId" on-delete="cascade" />
      <one-to-many class="Domain.RolesToAccess,Domain" />
    </bag>

役割:

<bag name="Accesses" table="RolesToAccess" cascade="none" lazy="false">
      <key column="RoleId" />
      <many-to-many column="RoleId" class="Domain.Compound,Domain" />
    </bag>

<bag name="RolesToAccess" cascade="save-update" inverse="true" lazy="false">
      <key column="RoleId" on-delete="cascade" />
      <one-to-many class="Domain.RolesToAccess,Domain" />
    </bag>

前述のように、モデルを汚染しないように、RolesToAccess プロパティを保護することができます。

于 2009-01-02T15:43:20.583 に答える
1

あなたがここで言うこと:

ロールを正常に削除する唯一の方法は、そのロールにリンクしているすべてのアーティファクトを照会し、アーティファクトのロールコレクションからロールを削除し、アーティファクトを更新してからロールを削除することです。簡素化されたシステムでは、ロールは他の任意の数のテーブル/オブジェクトに関連付けることができます。

必要ありません。アソシエーションテーブルをマップ(ドメインオブジェクトにする)したくない場合でも、最小限のコードで両端で削除を実行できます。

Role、Artifact、ArtifactAccess(リンクテーブル)の3つのテーブルがあるとします。マッピングには、ロールとアーティファクトのドメインオブジェクトのみがあります。どちらも多人数の協会のためのバッグを持っています。

役割:

    <bag name="Artifacts" table="[ArtifactAccess]" schema="[Dbo]" lazy="true"
        inverse="false" cascade="none" generic="true">
        <key column="[ArtifactID]"/>

        <many-to-many column="[RoleID]" class="Role" />
    </bag>

アーティファクト:

    <bag name="Roles" table="[ArtifactAccess]" schema="[Dbo]" lazy="true"
        inverse="false" cascade="none" generic="true">
        <key column="[RoleID]"/>

        <many-to-many column="[ArtifactID]" class="Role" />
    </bag>

ご覧のとおり、両端にはinverse=falseが指定されています。NHibernateのドキュメントでは、関連付けの一方の端を「逆」の端として選択することを推奨していますが、両方を「制御の端」として使用することを妨げるものは何もありません。更新または挿入を実行する場合、これは問題なく両方向から機能します。どちらかの端の削除を実行すると、関連付けテーブルが更新されていないため、FK違反エラーが発生します(true)。ただし、削除を実行する前に、コレクションをもう一方の端までクリアするだけでこれを解決できます。これは、「this」を使用している場合に、関連付けの「もう一方の」端を検索する場合よりもはるかに複雑ではありません。 ' 終わり。これが少し紛らわしい場合は、コード例を次に示します。制御できる端が1つしかない場合は、複雑な削除を行うために次のことを行う必要があります。

foreach(var artifact in role.Artifacts)
    foreach(var role in artifact.Roles)
        if(role == roleToDelete)
            artifact.Roles.Remove(role)
    artifact.Save();
roleToDelete.Delete();

役割を削除するときに私がすることは次のようなものです

roleToDelete.Artifacts.Clear(); //removes the association record
roleToDelete.Delete(); // removes the artifact record

これは1行の余分なコードですが、この方法では、関連付けのどちらの端が逆の端であるかを決定する必要はありません。また、完全に制御するために関連付けテーブルをマップする必要はありません。

于 2010-12-12T13:41:45.160 に答える
0

NHibernate はロール C# クラスにコレクションを持たずにこれを行う方法を提供する必要があると思いますが、SQL でいつでもこの動作を設定できます。データベース内の FK のカスケード削除を選択すると、自動的に削除されます。NHib のキャッシュに注意してください。

ただし、これを最後のリソースとして使用することを強くお勧めします。

于 2008-10-17T20:35:31.810 に答える
0

Role から へのマッピングを作成する必要がありますArtifact

遅延読み込みにし、保護された仮想メンバーにマップして、実際にアクセスされないようにすることができますが、NHibernate がArtefactAccessテーブルからロールを削除する必要があることを知るには、そのマッピングが必要です。

于 2008-10-17T23:08:30.063 に答える
0

関連付けテーブルのマッピングを作成し、Role_id が削除しようとしている値であるそのテーブルで delete を呼び出してから、ロール自体の削除を実行できます。これを行うのはかなり簡単です。

于 2008-10-17T17:30:00.403 に答える