在nhibernate中删除具有多对多关系的实体时,不会删除该关系

时间:2015-10-25 14:37:48

标签: c# nhibernate many-to-many hql

我正在使用NHibernate和C#。 我有两个实体,它们之间有很多关系。 当我删除父实体时,我只有它的ID,我用hql查询删除它。

我的问题是它只删除父实体而不删除它的关系。

我的实体看起来像这样:

public class Entity_A
{
      public virtual int Code { get; set; }
      public virtual int Id { get; set; }
      public virtual ICollection<Entity_B> Entities_B { get; set; }
}

public class Entity_B
{
      public virtual int Code { get; set; }
      public virtual ICollection<Entity_A> Entities_A { get; set; }
}

映射

public class EntityAMap : ClassMap<Entity_A>
{
      public EntityAMap()
      {
            Table("ENTITY_A");
            Id(x=>x.Code).GeneratedBy.Identity();
            Map(x=>x.Id).column("A_ID").Not.Nullable();
            HasManyToMany(x->x.Entities_B)
                    .LazyLoad()
                    .Generic()
                    .PropertyRef("Id")
                    .ChildKeyColumn("B_CODE")
                    .ParentKeyColumn("A_ID")
                    .Table("ENTITY_A_TO_ENTITY_B")
                    .Cascade.All();
      }
}

public class EntityBMap : ClassMap<Entity_B>
{
      public EntityBMap()
      {
            Table("ENTITY_B");
            Id(x=>x.Code).GeneratedBy.Identity();
            HasManyToMany(x->x.Entities_A)
                    .Generic()
                    .ChildPropertyRef("Code")
                    .ChildKeyColumn("A_ID")
                    .ParentKeyColumn("B_CODE")
                    .Table("ENTITY_A_TO_ENTITY_B")
                    .Cascade.All()
                    .Inverse();
      }
}

我的问题是,我应该更改什么,以便当我使用NHibernate HQL查询删除Entity_A时,它也会删除它与Entity_B的所有关系(来自表ENTITY_A_TO_ENTITY_B)。

1 个答案:

答案 0 :(得分:0)

如果您的代码看起来像这样:

ISession session = sessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();

String hqlDelete = "delete Entity_A ea where ea.Code = :code";
int deletedEntities = session.CreateQuery( hqlDelete )
        .SetString( "code", codeToDelete )
        .ExecuteUpdate();
tx.Commit();
session.Close();

(如果代码如上所示)那么:

  1. 我们使用HQL作为如何将实体加载到会话中的方式(让NHibernate发挥作用) -
  2. 但我们正在使用所谓的DML
  3. 请参阅文档:

    13.3. DML-style operations

      

    如前所述,自动和透明的对象/关系映射与对象状态的管理有关。这意味着对象状态在内存中可用,因此直接在数据库中操作(使用SQL数据操作语言(DML)语句:INSERT,UPDATE,DELETE)数据不会影响内存状态 ...

    主要是答案: ...不会影响内存状态...

    简单地说,这样我们只使用DML来有效地发出WRITE语句,同时使用HQL (在我们的实体之上的查询语言,而不是SQL)

    解决方案:

    1)将实例加载到内存中。我们可以使用HQL,或QueryOver,ICriteria ......这里重要的只是加载到内存中,转入ISession

    这样,DELETE上的NHiberante就可以开始发布所有预期的级联......

    2)使用.CreateSQLQuery()手动删除其余部分:

    session
         .CreateSQLQuery("DELTE FROM ENTITY_A_TO_ENTITY_B WHERE ENTITY_A = :id)
         .SetString( "id", idToDelete )
         .ExecuteUpdate();
    ...
    session.CreateQuery( hqlDelete )
    

    (第二种方法) 将支持有效的SQL语句(无需将实例加载到会话中),但需要更多编码我们这边(NHibernate可以使用其会话施放法术)