NHibernate不适用于树对象

时间:2014-08-13 06:32:40

标签: c# nhibernate tree fluent-nhibernate

我有这个类映射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();

表中没有任何变化,父母&#39;提交仍然设置。

这样测试失败了,因为TagActual有一个子集合,而这应该是空的

为什么NHibernate正确管理add操作,而不是remove

有没有办法在不向我的对象添加Parent属性并手动管理它的情况下执行此操作?

2 个答案:

答案 0 :(得分:0)

根据http://nhibernate.info/doc/nh/en/index.html#example-parentchild

,这就是NHibernate的设计方式

基本上,解决方案是添加一个额外的属性&#34; Parent&#34;谁负责这种关系:

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();
}

现在一切都应该按预期工作了......

答案 1 :(得分:0)

我找到了它:)

我犯了2个错误:

    地图中的
  • .ReadOnly();,没用了
  • 忘记了测试用例中的beginTrans

测试必须写成

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();
    }