在nhibernate中删除具有多对多关系的实体时,该关系不会被删除
本文关键字:删除 关系 实体 nhibernate | 更新日期: 2023-09-27 18:19:19
我正在使用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();
}
}
我的问题是,我应该改变什么,这样当我删除Entity_A与NHibernate HQL查询它也会删除所有的关系与Entity_B(从表ENTITY_A_TO_ENTITY_B)。
如果您的代码看起来像这样:
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();
(所以如果代码看起来像上面那样)那么:
- 我们不是使用HQL作为如何将实体加载到会话的方式(并让NHibernate完成魔术)-
- 但是我们使用的是所谓的DML
查看文档:
13.3。结合使用dml风格操作
如前所述,自动和透明的对象/关系映射与对象状态的管理有关。这意味着对象状态在内存中是可用的,因此直接在数据库中操作(使用SQL数据操作语言(DML)语句:INSERT, UPDATE, DELETE)数据不会影响内存中的状态…
大多数情况下这是答案:…
简单地说,这样我们就可以使用DML有效地发出WRITE语句,同时使用HQL (实体之上的查询语言,而不是SQL)
解决方案:
1)将实例加载到内存。我们可以使用HQL, QueryOver, iccriteria…这里重要的是LOAD INTO MEMORY, resp INTO session
这样,nhibernate在DELETE上就可以开始发出所有预期的级联…
2)使用.CreateSQLQuery()手动删除其余部分:
session
.CreateSQLQuery("DELTE FROM ENTITY_A_TO_ENTITY_B WHERE ENTITY_A = :id)
.SetString( "id", idToDelete )
.ExecuteUpdate();
...
session.CreateQuery( hqlDelete )
这个(第二种方法)将支持有效的SQL语句(不需要将实例加载到会话中),但是需要在我们这边编写更多的代码(NHibernate可以使用它的会话来施法)