在插入双向一对多关联后自动更新子集合ID

时间:2010-10-27 12:01:46

标签: c# nhibernate fluent-nhibernate

我确定此问题已经解决,但我找不到'重复'。所以问题是:

我有一个双向的一对多关联:文档评论。 comments表有一个指向文档表的外键(不可为空)。 课程是:

public class Document {
   public virtual Guid Id {get; set;}
   public virtual string Title {get; set;} 
   public virtual string Body {get; set;}
   public virtual IList<Comment> Comments {get; set;}
}

public class Comment {
   public virtual Guid Id {get; set;}
   public virtual Document Document {get; set;}
   public virtual string Body {get; set;}
}

//Mappings

public class DocumentMap : ClassMap<Document> {
    public DocumentMap(){
       Id(x => x.Id).GeneratedBy.GuidComb();
       Map(x=>x.Title);
       Map(x=>x.Body);
       HasMany(x=>x.Comments).Inverse().Cascade.All().AsBag();
    }
}

public class CommentMap : ClassMap<Comment> {
    public CommentMap(){
       Id(x => x.Id).GeneratedBy.GuidComb();
       Map(x=>Body);
       References(x=>x.Document).Column("DocumentId").Not.Nullable();
    }
}

//The problem

var existingDocument = FetchDocumentFromDatabase(someDocumentGuidId);
Console.WriteLine(existingDocument.Comments.Count()); //0
existingDocument.Comments.Add(new Comment { Document = existingDocument, Body = "Test"});
session.SaveOrUpdateCopy(existingDocument);//all OK
//commiting transaction etc
Console.WriteLine(existingDocument.Comments[0].Id); 
// 00000000-0000-0000-0000-000000000000

但我需要我的新评论ID!

评论被添加到数据库,但对象ID仍然是空的Guid。

如何将子对象ID作为父对象更新的一部分添加后自动填充它?

我正在使用NHibernate 3.0.0 Alpha 3(似乎非常稳定)和Fluent NHibernate v.1.1。

请建议。

更新1:所有更改都适用于DB(文档属性已更新以及添加了新注释)。

1 个答案:

答案 0 :(得分:2)

问题是你正在使用SaveOrUpdateCopy。这里发生的是existingDocument不用于持久存储到数据库。

来自http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-updating-detached

  

使用SaveOrUpdateCopy(Object o)可以避免最后一种情况。此方法将给定对象的状态复制到具有相同标识符的持久对象上。如果当前没有与会话关联的持久性实例,则将加载该实例。该方法返回持久化实例。如果给定的实例未保存或数据库中不存在,NHibernate将保存它并将其作为新的持久化实例返回。否则,给定实例不会与会话关联。在大多数具有分离对象的应用程序中,您需要两种方法SaveOrUpdate()SaveOrUpdateCopy()

这意味着existingDocument保持不变,NHibernate使用完全不同的实例来实际执行其操作。

那我们能做些什么呢。有几个选择:

  1. SaveOrUpdateCopy的结果应该是正确的Document。您可以将代码更改为:

    existingDocument = (Document)session.SaveOrUpdateCopy(existingDocument);
    
  2. 您可以切换到SaveOrUpdate。现在,我想有一个非常具体的原因,这对你来说可能是不可能的,因为你特意选择了SaveOrUpdateCopy。无论如何,SaveOrUpdate是你通常使用的;

  3. 您可以重新加载Document。这意味着在SaveOrUpdateCopy之后,你可以放置:

    var existingDocument = FetchDocumentFromDatabase(someDocumentGuidId);
    
  4. 如果您使用SaveOrUpdateCopy,因为existingDocument来自其他ISession,您还可以选择将existingDocument重新附加到当前ISession使用Lock()。在您将existingDocument锁定到新ISession之后,您可以使用SaveOrUpdate代替SaveOrUpdateCopy该实例,包括Comment将然后使用,Guid将被分配。