Nhibernate已删除集合项

时间:2013-05-17 13:18:52

标签: c# .net nhibernate fluent-nhibernate

我有2个班级:

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.Entries中删除一个项目时,我实际上并不想删除它,也不想杀死它。我只想将Entry.IsDeleted设置为true,我仍然希望Entry保持myClass'es 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");
}

5 个答案:

答案 0 :(得分:1)

看起来你真的不想从集合中删除它,也许将方法放在Entry上更像是

public void Delete(){
    IsDeleted = true;
}

而不是

myClassObj.Entries.Remove(myEntry);

DO

myEntry.Delete();

答案 1 :(得分:1)

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

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

on 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);

答案 2 :(得分:1)

如果我确实理解了您的方案,那么您希望最终采用删除操作:

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

1)为了保持关系,我们不会一直调用删除。

我们可以在Parent 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,我们只需添加级联(请参阅此处fluent mapping

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

3)要从Parent子集合的 lazy 加载中删除该项,我们可以在集合映射中附加where子句。请参阅此处的示例:where clause in the mapping

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

有关文档中where子句的更多信息:6.2. Mapping a Collection

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

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