NHibernate子删除问题

Posted

技术标签:

【中文标题】NHibernate子删除问题【英文标题】:NHibernate child deletion problem 【发布时间】:2010-04-13 07:17:55 【问题描述】:

假设,我使用这段代码在数据库中保存了一些权限:

RoleRepository roleRep = new RoleRepository();
Role role = new Role();
role.PermissionItems = Permission.GetList();
roleRep .SaveOrUpdate(role);

现在,当role.PermissionItems == null 时,我需要此代码来删除与角色关联的 PermissionItem。

代码如下:

RoleRepository roleRep = new RoleRepository();
Role role = roleRep.Get(roleId);
role.PermissionItems = null;
roleRep .SaveOrUpdate(role);

但这并没有发生。

应对这种情况的正确方法应该是什么?

我应该更改什么/如何更改,hbm 文件或持久性代码?

角色.cs

public class Role

    public virtual string RoleName  get; set; 
    public virtual bool IsActive  get; set; 
    public virtual IList<Permission> PermissionItems  get; set; 

角色.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="POCO" namespace="POCO">
  <class name="Role" table="Role">
    <id name="ID" column="ID">
      <generator class="native" />
    </id>    
    <property name="RoleName" column="RoleName" />
    <property name="IsActive" column="IsActive" type="System.Boolean" />
    <bag name="PermissionItems" table="Permission" cascade="all" inverse="true">
      <key column="RoleID"/>
      <one-to-many class="Permission" />
    </bag>    
  </class>  
</hibernate-mapping>

Permission.cs

public class Permission

    public virtual string MenuItemKey  get; set; 
    public virtual int RoleID  get; set; 
    public virtual Role Role  get; set; 

Permission.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="POCO" namespace="POCO">
  <class name="Permission" table="Permission">
    <id name="ID" column="ID">
      <generator class="native"/>
    </id>
    <property name="MenuItemKey" column="MenuItemKey" />
    <property name="RoleID" column="RoleID" />
    <many-to-one name="Role" column="RoleID" not-null="true" cascade="all">      
    </many-to-one>
  </class>
</hibernate-mapping>

Repository.cs

......
    public void SaveOrUpdate(T obj)
            
                try
                
                    if (!_session.Transaction.IsActive)
                    
                        _session.BeginTransaction();
                        _session.SaveOrUpdate(obj);
                        _session.Transaction.Commit();
                        _session.Flush();
                    
                    else
                    
                        throw new Exception(CustomErrorMessage.TransactionAlreayInProgress);
                    
                
                catch (Exception ex)
                
                    _session.Transaction.Rollback();
                    _session.Clear();

                    throw ex;
                
            
......

RoleRepository.cs

public class RoleRepository : Repository<Role>, IRoleRepository
    
    

【问题讨论】:

SaveOrUpdate() 是什么样的? 请查看更新。它是正在使用的存储库模式。 正常的删除方式是什么?我应该只依赖 SaveOrDelete() 吗? 【参考方案1】:

将 Role 映射更改为 cascade all-delete-orphan 以便删除孤立的 Permission 记录:

<bag name="PermissionItems" table="Permission" cascade="all-delete-orphan" inverse="true">

并在集合上调用 clear 而不是将其设置为 null:

role.PermissionItems.Clear();

刷新会话时将删除孤立的权限记录。

PS:存储库中的 catch 块应该调用 throw; 而不是 throw ex;

【讨论】:

以上是关于NHibernate子删除问题的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate 级联删除不适用于一对多关联

将新的“子”列表分配给“父”时 NHibernate 孤儿

对于不支持子查询的 NHibernate-to-LINQ 是不是有任何解决方法?

使用 NHibernate/Hibernate 将实体类型转换为子类型

nHibernate 保存一对多

NHibernate Eager 加载多级子对象