对已删除的集合项进行Nhibernate

本文关键字:Nhibernate 集合 删除 | 更新日期: 2023-09-27 18:14:11

我有两个类:

public class Entry{
  ...
  public virtual IsDeleted {get;set;}
  public virtual int MyClsId {get;set;}
  public virtual MyClass MyCls {get;set;}
}
public class MyClass{
  ...
  public virtual ICollection<Entry> Entries {get;set;}
}

当我从MyClass中移除一个项目时。我不想删除它,也不想终止关系。我只想设置条目。IsDeleted为true,我仍然希望条目保持myClass的Id;

myClassObj.Entries.Remove(myEntry); // after this line myEntry.MyCls.Id 
                                    // should stay intact. myEntry.IsDeleted 
                                    // should be set to true;

我该怎么做呢?我试过拦截器,但不能让它工作。

编辑

映射:

除了映射我使用的字段:

MyClassMap : ...
{
  HasMany(x => Entries).KeyColumn("MyClsId");
}

对已删除的集合项进行Nhibernate

这似乎不像你真的想从集合中删除这个,也许它会更有意义的Entry上放一个方法,就像

public void Delete(){
    IsDeleted = true;
}

而不是

myClassObj.Entries.Remove(myEntry);

myEntry.Delete();

在这种情况下,您必须更新您的实体而不是删除。尝试使用

更改映射
// set cascade to all to add/update/delete this childs by parent.
HasMany(x => Entries).KeyColumn("MyClsId").Cascade.All();

MyClass上创建一个方法更新它:

public class MyClass{
  ...
  public virtual ICollection<Entry> Entries {get;set;}
  public void DeleteEntry(Entry entry)
  {
      entry.IsDelete = true;   
  }
}

,当你想设置一个Entry对象为IsDeleted到true时,你调用DeleteEntry方法传递对象,只是持久化MyClass实例,孩子们将一起持久化。

session.SaveOrUpdate(myClassObj);

如果我正确理解您的场景,您希望有一个Delete操作,该操作将在最后:

  • 保持关系
  • 标记为IsDeleted
  • 不要将其保存在父的集合中(这里我不确定,但如果需要,我们有下面的解决方案)

1)为了保持关系,我们不需要一直调用delete。

我们可以在父RemoveEntry

上引入一个方法
public class MyClass 
{
  public virtual void RemoveEntry(Entry entry) // or by index, name
  {
     // some checks over Entries collection
     entry.IsDeleted = true;
  }
}

当MyClass实例被更新为session.Update(myClass)时,所有条目也将被更新

2)为了将其标记为IsDeleted,我们只需附加级联(在这里查看更多流畅映射

)
MyClassMap : ...
{
  HasMany(x => Entries)
   .KeyColumn("MyClsId")
   .Cascade.All()
}

3)要从惰性加载的Parent子集合中删除该项,可以在集合映射中附加where子句。where子句中的映射

MyClassMap : ...
{
  HasMany(x => Entries)
    .KeyColumn("MyClsId")
    .Cascade.All()
    .Where("IsDeleted = 0"); // that will load only IsDeleted == false lazily
}

关于文档中where子句的更多信息:6.2。映射集合

实现您想要的一种方法是不直接使用实体,而是使用DTO,这是您的实体的副本(具有所有集合项)。在DTO上执行删除操作(因此已删除的集合项对应用程序是不可见的),稍后当您想要保存实体时,只需将其与DTO同步(对于已删除的集合项,将IsDeleted标志设置为true)。多做了一点工作,但它达到了你想要的效果

我必须在MyClass中创建一个额外的属性,这似乎是唯一可行的解决方案。

public virtual IEnumerable<Entry> NotDeletedEntries{get{return Entries.Where(x=>x.IsDeleted == false);}}