NHibernate不支持树型对象

本文关键字:对象 树型 不支持 NHibernate | 更新日期: 2023-09-27 18:17:41

我有一个映射Tag对象树的类:

public class Tag
{
    public int Id { get; set; }
    public int Description { get; set; }
    private IList<Tag> childTag = new List<Tag>();
    public virtual IEnumerable<Tag> ChildTag
    { get { return childTag.ToArray(); } }
    public virtual void Add(Tag child)
    { childTag .Add(child); }
    public virtual bool Remove(Tag child)
    { return childTag .Remove(child); }
}

与此地图:

public TagMap()
    {
        Id(x => x.Id)
            .Column("Kint_T01_IdTag")
            .GeneratedBy.Assigned();
        HasMany(x => x.ChildTag)
                .KeyColumn("ParentId")
                .Cascade.All()
                .Access.CamelCaseField().ReadOnly();
    }

当我运行这个测试

        Tag Tag= fixture.Build<Tag>().Do(x => x.Add(fixture.Create<Tag>())).Create();
        Tag TagActual;
        using (IUnitOfWork uow = new UnitOfWork())
        {
            uow.openConnection();
            uow.BeginTran();
            uow.TagRepository.Create(Tag);
            uow.commit();
            Tag.Rmove(Tag.ChildTag.First());
            uow.TagRepository.Update(Tag);
            uow.commit();
            uow.closeConnection();
            uow.openConnection();
            TagActual = uow.TagRepository.GetById(Tag.Id);
            TagActual.ShouldBeEquivalentTo(Tag);
            uow.closeConnection();
        }

失败是因为TagActual。ChildTag包含一个子元素,即使我将它从父集合中移除。

我看到在 之后
uow.TagRepository.Create(Tag);
uow.commit();

表中有两个记录,并且正确设置了子表的parent属性

Tag.Rmove(Tag.ChildTag.First());工作正常,之后集合为空

但在

之后
uow.TagRepository.Update(Tag);
uow.commit();

表中没有任何变化,'父'字段仍然设置。

这样测试就失败了,因为TagActual有一组子元素,而this应该是空的

为什么NHibernate可以正确管理add而不能管理remove

有没有办法做到这一点,而不添加Parent属性到我的对象和手动管理它?

NHibernate不支持树型对象

我找到了

我犯了两个错误:

  • .ReadOnly();在地图,它是无用的
  • 在测试用例中忘记了beginTrans

test必须这样写

Tag Tag= fixture.Build<Tag>().Do(x => x.Add(fixture.Create<Tag>())).Create();
    Tag TagActual;
    using (IUnitOfWork uow = new UnitOfWork())
    {
        uow.openConnection();
        uow.BeginTran();
        uow.TagRepository.Create(Tag);
        uow.commit();
        uow.BeginTran();
        Tag.Rmove(Tag.ChildTag.First());
        uow.TagRepository.Update(Tag);
        uow.commit();
        uow.closeConnection();
        uow.openConnection();
        TagActual = uow.TagRepository.GetById(Tag.Id);
        TagActual.ShouldBeEquivalentTo(Tag);
        uow.closeConnection();
    }

这就是NHibernate的设计方式,根据http://nhibernate.info/doc/nh/en/index.html#example-parentchild

基本上,解决方案是在添加一个额外的属性"Parent",它负责关系:

public class Tag
{
    public int Id { get; set; }
    public int Description { get; private set; }
    private IList<Tag> childTag = new List<Tag>();
    private Tag parentTag;
    public virtual IEnumerable<Tag> ChildTag { get { return childTag.ToArray(); } }
    public virtual void Add(Tag child) { childTag .Add(child); }
    public virtual bool Remove(Tag child) { return childTag .Remove(child); }
}

与此地图:

public TagMap()
{
    Id(x => x.Id)
        .Column("Kint_T01_IdTag")
        .GeneratedBy.Assigned();
    Reference(x => x.ParentTag).Access.CamelCaseField();
    HasMany(x => x.ChildTag)
            .Inverse()
            .KeyColumn("ParentId")
            .Cascade.AllDeleteOrphan()
            .Access.CamelCaseField().ReadOnly();
}