(流畅的)当合同转换器构造业务对象时,nHibernate不会从集合中删除项目

时间:2013-03-28 14:16:45

标签: nhibernate fluent-nhibernate

我已经在几天内搜索了我的问题的答案,我已经尝试了大部分提示/答案,甚至查看了nHibernate生成的数百行日志,但我找不到办法获取我的映射工作..当被要求SaveOrUpdate时,nHiberante仍然拒绝生成任何删除语句。

我有三个独立的实体,人物,房子和房间...真实的话,每个人都有一个房子,每个房子可以有多个房间,房子和房间之间的映射是一对多的预期我希望在Person和House之间进行一对一的映射,然后我在流畅的nHibernate wiki上阅读,它说它实际上是一个很多(人)到一个(房子),因为在数据库级别没有什么可以阻止多个人共享同一所房子。我想这是有道理的,所以我的数据库架构和类映射设计如下:

CREATE TABLE [dbo].[Person](
    [PersonId] [int] IDENTITY(1,1) NOT NULL,
    [HouseId] [int] NOT NULL
)

CREATE TABLE [dbo].[House](
    [HouseId] [int] IDENTITY(1,1) NOT NULL,
    [HouseName] [varchar](500) NOT NULL
)

CREATE TABLE [dbo].[Room](
    [RoomId] [int] IDENTITY(1,1) NOT NULL,
    [HouseId] [int] NOT NULL
)


HouseId on [Person] and [Room] are both foreign keys referencing HouseId from [House] table

    public class PersonMap : ClassMap<Person>
    {
        public PersonMap()
        {
            Table("Person")
            Id (x=>x.Id).Column("PersonId").GeneratedBy.Identity().UnsavedValue(0);
            Reference(x=>x.House).Column("HouseId").ForeignKey("HouseId").Not.LazyLoad().Cascade.All();
        }
    }

    public class HouseMap : HouseMap<Room>
    {
        public RoomMap()
        {
            Table("House")
            Id (x=>x.Id).Column("HouseId").GeneratedBy.Identity().UnsavedValue(0);

            HasMany(x => x.Persons)
                .KeyColumn("HouseId")
                .Not.LazyLoad()
                .Cascade.AllDeleteOrphan().Inverse();

            HasMany(x => x.Rooms)
                .KeyColumn("HouseId")
                .Not.LazyLoad()
                .Cascade.AllDeleteOrphan().Inverse();
        }
    }

    public class RoomMap : ClassMap<Room>
    {
        public RoomMap()
        {
            Table("Room")
            Id (x=>x.Id).Column("RoomId").GeneratedBy.Identity().UnsavedValue(0);
            Reference(x=>x.House).Column("HouseId").ForeignKey("HouseId").Not.LazyLoad().Cascade.All();
        }
    }

Class House分别拥有两个Person和Room类型的列表,Person和Room类都拥有一个返回House对象的引用。

所以我创建了一个House的实例并设置了它的两个子列表Person(一个1)和Room(多个房间),并且还将Person / Rooms的属性链接回House ..并使用session.SaveOrUpdate来保存一切都很好的人。

然后我尝试检索Person的实例,并从Person.House.List中删除一个房间并将room.House设置为null以完全中断引用,然后使用session.SaveOrUpdate再次保存Person(让我们称之为Person) A),,, nHibernate正确生成删除语句,删除没有链接到其父House的孤儿房间......到目前为止一直这么好......

这是我的问题开始...在我的应用程序中,我需要将对象Person转换为PersonContract,然后将其发送到客户端,客户端能够从PersonContract.HouseContract中删除roomContract并发送一个PersonContract的副本。请注意,在PersonContract中,没有双边引用,即PersonContract具有HouseContract的一个属性,而HouseContract仅包含RoomContract列表,因此HouseContract不保留PersonContract列表,而RoomContract没有HouseContract属性。

然后在服务器端,我将PersonContract转换回Person对象,转换器负责创建Person,Room和house的所有新实例,并设置它们的ID并在它们之间构建所有双边引用。

问题是......当我在Person对象上使用session.SaveOrUpdate时(合同转换后),nHibernate似乎忽略了一个房间已从集合中删除但它更新或插入作业的事实。

我仔细检查了我的合同转换器,以确保所有属性/引用/ ID都已正确设置,并且它看起来与上面的人A完全相同...但我不明白为什么nHibernate没有做这里的工作。

我在Person / Room / House上覆盖了Equals和GetHashCode以返回其id。

我观察到的另一个事实是,当我在转换后的Person对象上使用session.SaveOrUpdate时,nHibernate生成了大量的Update语句,即使该值没有真正改变,看起来好像nHibernate不知道状态持久化的Person对象,所以选择通过使用Id ...

识别它来更新所有内容

我对nHibernate很新...所以如果我在这里做了一些可怕的错误,请告诉我:))

更新:如果我从House和Room之间的一对多映射中删除Inverse,那么nHibernate会将删除的Room的房屋ID设置为NULL ...比根本不删除房间更好但我真的希望它从DB中移除孤儿房间。

更新2 :Person.Merge on Person正在运行(SaveOrUpdate没有)....虽然我不明白为什么...

1 个答案:

答案 0 :(得分:1)

尝试在事务中包装保存/更新:

using (ITransaction transaction = session.BeginTransaction())
{
    session.Save(SomeObject);
    transaction.Commit();
}
相关问题