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

chu*_*nce 0 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; }
}
Run Code Online (Sandbox Code Playgroud)

在我的邻居地图中我有:

   mapping.HasMany(x => x.Addresses)
        .Inverse()
        .KeyColumn("NeighborhoodFk")
        .Cascade.All()
        .AsBag();
Run Code Online (Sandbox Code Playgroud)

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

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();
Run Code Online (Sandbox Code Playgroud)

我将在实体上获得"未保存的瞬态实体"错误,Person因为它附加到瞬态实体Address.

我能看到的唯一方法是保存第address一个,在更新neighborhood后再次调用数据库进行更新,搜索address我刚添加的,附加person然后再次保存.

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

Kei*_*thS 5

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

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