我确定此问题已经解决,但我找不到'重复'。所以问题是:
我有一个双向的一对多关联:文档和评论。 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(文档属性已更新以及添加了新注释)。
答案 0 :(得分:2)
问题是你正在使用SaveOrUpdateCopy
。这里发生的是existingDocument
不用于持久存储到数据库。
来自http://nhibernate.info/doc/nh/en/index.html#manipulatingdata-updating-detached:
使用
SaveOrUpdateCopy(Object o)
可以避免最后一种情况。此方法将给定对象的状态复制到具有相同标识符的持久对象上。如果当前没有与会话关联的持久性实例,则将加载该实例。该方法返回持久化实例。如果给定的实例未保存或数据库中不存在,NHibernate将保存它并将其作为新的持久化实例返回。否则,给定实例不会与会话关联。在大多数具有分离对象的应用程序中,您需要两种方法SaveOrUpdate()
和SaveOrUpdateCopy()
。
这意味着existingDocument
保持不变,NHibernate使用完全不同的实例来实际执行其操作。
那我们能做些什么呢。有几个选择:
SaveOrUpdateCopy
的结果应该是正确的Document
。您可以将代码更改为:
existingDocument = (Document)session.SaveOrUpdateCopy(existingDocument);
您可以切换到SaveOrUpdate
。现在,我想有一个非常具体的原因,这对你来说可能是不可能的,因为你特意选择了SaveOrUpdateCopy
。无论如何,SaveOrUpdate
是你通常使用的;
您可以重新加载Document
。这意味着在SaveOrUpdateCopy
之后,你可以放置:
var existingDocument = FetchDocumentFromDatabase(someDocumentGuidId);
如果您使用SaveOrUpdateCopy
,因为existingDocument
来自其他ISession
,您还可以选择将existingDocument
重新附加到当前ISession
使用Lock()
。在您将existingDocument
锁定到新ISession
之后,您可以使用SaveOrUpdate
代替SaveOrUpdateCopy
该实例,包括Comment
将然后使用,Guid
将被分配。