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

发布于 2024-09-29 12:34:23 字数 1652 浏览 1 评论 0原文

我确信这个问题以前已经解决过,但我找不到“重复”。所以问题是:

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

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!

注释已添加到 DB,但对象 Id 仍然是空 Guid。

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

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

请指教。

更新 1:所有更改都会很好地传播到数据库(更新文档属性并添加新注释)。

I'm sure this problem has been addressed before but I can't find a 'duplicate'. So the question is:

I have a bidirectional one-to-many association: document and comments.
The comments table has a foreign key (not nullable) pointing to documents table.
The classes are:

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

But I need my new comment Id here!

The comment is added OK to DB but the object Id is still an empty Guid.

How do I automatically fill child object Ids after they were added as part of parent object update?

I'm using NHibernate 3.0.0 Alpha 3 (seems to be very stable) and Fluent NHibernate v.1.1.

Please advice.

UPDATE 1: all changes propage to DB just fine (document properties are updated as well as new comments are added).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

桃扇骨 2024-10-06 12:34:23

问题是您正在使用 SaveOrUpdateCopy。这里发生的情况是 existingDocument 不用于持久化到数据库。

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

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

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

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

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

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

  3. 您可以重新加载文档。这意味着在 SaveOrUpdateCopy 之后,您可以输入:

    var现有文档 = FetchDocumentFromDatabase(someDocumentGuidId);
    
  4. 如果您使用 SaveOrUpdateCopy 因为 existingDocument 来自不同的 ISession,您还可以选择使用 Lock()existingDocument 重新附加到当前 ISession。将 existingDocument“锁定”到新的 ISession 后,您可以使用 SaveOrUpdate 而不是 SaveOrUpdateCopy然后将使用该实例,包括 Comment 并分配 Guid

The problem is that you're using SaveOrUpdateCopy. What happens here is that existingDocument is not used to persist to the database.

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

The last case can be avoided by using SaveOrUpdateCopy(Object o). This method copies the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. The method returns the persistent instance. If the given instance is unsaved or does not exist in the database, NHibernate will save it and return it as a newly persistent instance. Otherwise, the given instance does not become associated with the session. In most applications with detached objects, you need both methods, SaveOrUpdate() and SaveOrUpdateCopy().

What this means is that existingDocument is left alone and NHibernate uses entirely different instances to actually perform its actions on.

So what can we do. There are a few options:

  1. The result from SaveOrUpdateCopy should be the correct Document. You can change your code to:

    existingDocument = (Document)session.SaveOrUpdateCopy(existingDocument);
    
  2. You can switch to SaveOrUpdate. Now, I guess there is a very specific reason this may not be possible for you, because you specifically chose SaveOrUpdateCopy. Anyway, SaveOrUpdate is what you'd normally use;

  3. You can reload the Document. This means that after the SaveOrUpdateCopy, you could put:

    var existingDocument = FetchDocumentFromDatabase(someDocumentGuidId);
    
  4. If you are using SaveOrUpdateCopy because existingDocument came from a different ISession, you can also choose to reattach the existingDocument to the current ISession using Lock(). After you've 'locked' in the existingDocument into the new ISession, you can use SaveOrUpdate instead of SaveOrUpdateCopy and that instance, including the Comment will then be used and the Guid will be assigned.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文