Question

J'ai un scénario dans un système que j'ai essayé de simplifier du mieux que je pouvais. Nous avons un tableau des artefacts (permet de les appeler) de n'importe quel nombre de rôles de sécurité et les rôles de sécurité peuvent accéder à un nombre quelconque d'artefacts. En tant que tel, nous avons 3 tables dans la base de données - une qui décrit les artefacts, une qui décrit les rôles et une table d’association plusieurs à plusieurs reliant l’identifiant de l’artéfact à l’ID du rôle.

En ce qui concerne le domaine, nous avons deux classes - une pour un rôle et une pour un artefact. la classe artefact a une propriété IList qui renvoie une liste de rôles pouvant y accéder. (Les rôles n'offrent toutefois pas de propriété permettant d'obtenir des artefacts accessibles.)

En tant que tel, le mappage nhibernate pour un artefact contient les éléments suivants:

<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>

Tout fonctionne correctement et si je supprime un artefact, la table d'association est nettoyée correctement et toutes les références entre l'artefact et les rôles supprimés sont supprimées (le rôle n'est pas supprimé, mais correctement - car nous ne voulons pas d'orphelins. supprimé).

Le problème est le suivant: comment supprimer un rôle et le faire effacer automatiquement le tableau d'association. Si j'essaie actuellement de supprimer un rôle, j'obtiens une contrainte de référence car il y a encore des entrées dans la table d'association pour le rôle. Le seul moyen de supprimer un rôle consiste à interroger tous les artefacts liés à ce rôle, à supprimer le rôle de la collection de rôles de l'artefact, à mettre à jour les artefacts, puis à supprimer le rôle. système simplifié, les rôles peuvent être associés à un nombre quelconque d'autres tables / objets.

Je dois pouvoir laisser entendre à NHibernate que je souhaite effacer cette table d'association chaque fois que je supprime un rôle. Est-ce possible, et si oui, comment puis-je le faire?

Merci pour toute aide.

Était-ce utile?

La solution

Puisque je cherchais cette réponse et que je trouvais ce fil sur Google (sans réponse), je pensais que je posterais ma solution à ce sujet. Avec trois tables: Role, RolesToAccess (ManyToMany), Access.

Créez les mappages suivants: Accès:

<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>

Rôles:

<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>

Comme mentionné ci-dessus, vous pouvez protéger les propriétés RolesToAccess afin qu'elles ne polluent pas votre modèle.

Autres conseils

Ce que vous dites ici:

  

Le seul moyen de supprimer un rôle consiste à interroger tous les artefacts liés à ce rôle, à supprimer le rôle de la collection de rôles de l'artefact, à mettre à jour les artefacts, puis à supprimer le rôle. Dans le système non simplifié, les rôles peuvent être associés à un nombre quelconque d’autres tables / objets.

N'est pas nécessaire. Supposons que vous ne vouliez pas mapper la table d'association (en faire un objet de domaine), vous pouvez toujours effectuer des suppressions aux deux extrémités avec un code minimal.

Supposons qu'il existe 3 tables: Role, Artifact et ArtifactAccess (la table de liens). Dans votre correspondance, vous ne disposez que d'objets de domaine pour le rôle et l'artefact. Les deux ont un sac pour l'association plusieurs-beaucoup.

Rôle:

    <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>

Artefact:

    <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>

Comme vous pouvez le constater, inverse = false est spécifié aux deux extrémités. La documentation de NHibernate vous recommande de choisir une extrémité de votre association comme extrémité "inverse", mais rien ne vous empêche d'utiliser les deux comme "extrémité de contrôle". Lorsque vous effectuez des mises à jour ou des insertions, cela fonctionne dans les deux sens sans accroc. Lorsque vous effectuez des suppressions de l'une des extrémités, vous obtenez une erreur de violation FK car la table d'association n'est pas mise à jour, true. Mais vous pouvez résoudre ce problème en effaçant simplement la collection à l’autre extrémité, avant d’effectuer la suppression, ce qui est beaucoup moins complexe que ce que vous faites, qui consiste à rechercher dans l’autre extrémité de l’association s’il existe des utilisations de ' fin. Si ceci est un peu déroutant, voici un exemple de code. Si vous n’avez qu’une extrémité dans le contrôle, pour votre suppression complexe, vous devez effectuer:

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

Ce que je fais lorsque je supprime un rôle ressemble à quelque chose comme

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

C'est une ligne de code supplémentaire, mais de cette façon, vous n'avez pas besoin de décider à quelle extrémité de l'association correspond l'extrémité inverse. Vous n'avez également pas besoin de mapper la table d'association pour un contrôle total.

Vous pouvez créer un mappage pour la table d'association, puis appeler delete sur cette table où id_rôle correspond à la valeur que vous êtes sur le point de supprimer, puis procéder à la suppression du rôle lui-même. Cela devrait être assez simple.

Bien que je pense que NHibernate doit fournir un moyen de le faire sans avoir la collection dans la classe des rôles C #, vous pouvez toujours définir ce comportement en SQL. Sélectionnez la suppression en cascade pour le FK dans la base de données et cela devrait être automatique, faites attention au cache de NHib.

Mais je vous conseille vivement de l'utiliser comme dernière ressource.

Vous devez créer un mappage entre le rôle et Artefact .

Vous pouvez effectuer un chargement paresseux et le mapper sur un membre virtuel protégé, de sorte qu'il ne soit jamais utilisé, mais vous avez besoin de ce mappage pour que NHibernate sache qu'il doit supprimer les rôles du . ArtefactAccess table

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top