一次在NHibernate中保存多个子实体

时间:2010-09-20 17:27:45

标签: nhibernate fluent-nhibernate s#arp-architecture

我在NHibernate中收到“保存未保存的瞬态实体”错误。我有一个聚合根neighborhood,其中包含addressesperson,这里有一些快速伪代码来解释这种关系:

public class Neighborhood {
   public virtual int Id { get; set; }
   public virtual IList<Address> Addresses { get; set; }
}

public class Address {
   public virtual int Id { get; set; }
   public virtual string Address { get; set; }
   public virtual Person Person { get; set; } //Assume only one person per address
}

public class Person {
   public virtual int Id { get; set; }
   public virtual string Name { get; set; }
}

在我的邻居地图中,我有:

   mapping.HasMany(x => x.Addresses)
        .Inverse()
        .KeyColumn("NeighborhoodFk")
        .Cascade.All()
        .AsBag();

在我的代码中,我经常想要创建一个并同时关联一个地址和人员:

var address = new Address();
var person = new Person();

var address.Person = person;

var neighborhood = neighborhoodRepository.Get(id);

neighborhood.Add(address);

neighborhoodRepository.DbContext.BeginTransaction();
neighborhoodRepository.SaveOrUpdate(neighborhood);
neighborhoodRepository.DbContext.CommitTransation();

我会在Person实体上收到“未保存的瞬态实体”错误,因为它附加到瞬态实体Address

我可以看到的唯一方法是首先保存address,在更新后再次调用数据库以更新neighborhood,搜索我刚刚添加的address ,附上person,然后再次保存。

有什么我想念的东西让这更容易吗?这似乎是一个常见的用例,我不想在数据库中进行一堆往返。

1 个答案:

答案 0 :(得分:5)

确保将地图到人的映射的“级联”属性设置为“保存更新”或“全部”。你有从邻居到地址的级联,但你没有声明这个较低的级联存在。如果不是,那么您收到此错误不是因为Person附加到临时地址,而是因为地址引用了临时Person。

如果由于某种原因无法生成此级联,请首先保存Person,然后保存邻居,它将级联到地址,ORM将在其会话中找到引用的Person并设置引用。这可能会导致一些额外的“往返”,具体取决于您是否让NH或DB生成自动编号列。 NHibernate很棘手,因为它会在好的和准备好的情况下进行DB调用,这可能是在整个对象图在NH会话之后,或者仅仅是人。无论哪种方式,它都会对每个持久化对象的数据库进行插入调用,因此无论将项目添加到会话中的代码如何,它都会进行多次“往返”。