【问题标题】:When deleting an entity with many to many relationship in nhibernate the relationship is not deleted在 nhibernate 中删除具有多对多关系的实体时,不会删除该关系
【发布时间】:2015-10-25 14:37:48
【问题描述】:

我正在使用 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)。

【问题讨论】:

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


    【解决方案1】:

    如果您的代码如下所示:

    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

    查看文档:

    13.3. DML-style operations

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

    答案大多是这样的:...不会影响内存状态...

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

    解决方案:

    1) 将实例加载到内存中。我们可以使用HQL,或者QueryOver,ICriteria...这里重要的只是LOAD INTO MEMORY,resp into 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 可以通过它的会话来施法)

    【讨论】:

    • 删除经常发生,实体很大,所以加载到内存中很重。我需要一种删除关系的方法,即使它是一个大的 hql 语句
    • 我在扩展答案中展示了另一种方式。希望它有所帮助;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    相关资源
    最近更新 更多