one many example c# nhibernate many-to-many

c# - many - nhibernate list



Many to Many eliminar cascada en NHibernate (5)

Tengo un escenario en un sistema que he tratado de simplificar lo mejor que puedo. Tenemos una tabla de artefactos (le permite llamar), se puede acceder a los artefactos por cualquier número de roles de seguridad y los roles de seguridad pueden acceder a cualquier cantidad de artefactos. Como tal, tenemos 3 tablas en la base de datos, una que describe artefactos, una que describe roles y una tabla de asociación de muchos a muchos que vincula la identificación del artefacto con la Identificación del rol.

En cuanto a dominio, tenemos dos clases: una para un rol y otra para un artefacto. la clase artefacto tiene una propiedad IList que devuelve una lista de roles que pueden acceder a ella. (Los roles, sin embargo, no ofrecen una propiedad para obtener artefactos a los que se pueda acceder).

Como tal, el mapeo de nhibernate para artefacto contiene lo siguiente;

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

Todo funciona bien y si elimino un artefacto, la tabla de asociación se limpia de forma adecuada y todas las referencias entre el artefacto eliminado y los roles se eliminan (aunque el rol no se elimina correctamente, ya que no queremos que los huérfanos se eliminen).

El problema es cómo eliminar un rol y hacer que aclare la tabla de asociación automáticamente. Si actualmente intento eliminar una función, obtengo una restricción de referencia ya que todavía hay entradas en la tabla de asociación para la función. La única forma de eliminar un rol con éxito es consultar todos los artefactos que se vinculen con ese rol, eliminar el rol de la colección de roles del artefacto, actualizar los artefactos y luego eliminar el rol, no muy eficiente o agradable, especialmente cuando se encuentra en el sistema simplificado, los roles pueden asociarse con cualquier cantidad de otras tablas / objetos.

Necesito poder indicarle a NHibernate que quiero que esta tabla de asociación se borre cada vez que elimine un rol. ¿Es posible? Y si es así, ¿cómo lo hago?

Gracias por cualquier ayuda.


Lo que dices aquí:

La única forma de eliminar un rol con éxito es consultar todos los artefactos que se vinculen con ese rol, eliminar el rol de la colección de roles del artefacto, actualizar los artefactos y luego eliminar el rol, no muy eficiente o agradable, especialmente cuando se encuentra en el sistema simplificado, los roles pueden asociarse con cualquier cantidad de otras tablas / objetos.

No es necesario. Supongamos que no desea asignar la tabla de asociación (convertirlo en un objeto de dominio), pero puede realizar eliminaciones en ambos extremos con un código mínimo.

Digamos que hay 3 tablas: Role, Artifact y ArtifactAccess (la tabla de enlaces). En su asignación, solo tiene objetos de dominio para Rol y Artefacto. Ambos tienen una bolsa para la asociación many-many.

Papel:

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

Artefacto:

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

Como puede ver, ambos extremos tienen inversa = falso especificado. La documentación de NHibernate le recomienda elegir un extremo de su asociación como el extremo "inverso", pero nada le impide usar ambos como "extremo controlador". Al realizar actualizaciones o inserciones, esto funciona desde ambas direcciones sin ningún problema. Al realizar eliminaciones de cualquiera de los extremos, se obtiene un error de infracción FK porque la tabla de asociación no está actualizada, es verdadera. Pero puede resolver esto simplemente borrando la colección al otro extremo, antes de realizar la eliminación, que es mucho menos compleja que lo que hace, que está buscando en el "otro" extremo de la asociación si hay usos de ''esto '' fin. Si esto es un poco confuso, aquí hay un ejemplo de código. Si solo tiene un extremo en control, para su eliminación compleja debe hacer:

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

Lo que hago al eliminar un rol es algo así como

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

Es una línea adicional de código, pero de esta manera no es necesario tomar una decisión sobre qué extremo de la asociación es el extremo inverso. Tampoco necesita asignar la tabla de asociación para un control total.


Puede hacer una asignación para la tabla de asociación y luego invocar eliminar en esa tabla donde Role_id es el valor que está a punto de eliminar, y luego realizar la eliminación del rol en sí. Debería ser bastante sencillo hacer esto.


Aunque creo que NHibernate debe proporcionar una forma de hacerlo sin tener la colección en la clase de roles C #, siempre puede establecer este comportamiento en SQL. Seleccione en cascada eliminar para el FK en la base de datos y debe ser automático, solo tenga cuidado con la memoria caché de NHib.

Pero le recomiendo que use esto como último recurso.


Debe crear una asignación de Rol a Artifact .

Puede hacer que la carga sea lenta y asignarla a un miembro virtual protegido, de modo que nunca se acceda a ella, pero necesita esa asignación allí para que NHibernate sepa que tiene que eliminar los roles de la tabla ArtefactAccess


Como estaba buscando esta respuesta y encontré este hilo en google (sin una respuesta), pensé en publicar mi solución. Con tres tablas: Rol, RolesToAccess (ManyToMany), Acceso.

Cree las siguientes asignaciones: Acceso:

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

Roles:

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

Como se mencionó anteriormente, puede proteger las propiedades de RolesToAccess para que no contaminen su modelo.