NHibernate,更新Session之外的只读集合(更改了一个不可变的集合实例)

时间:2014-08-12 12:24:32

标签: c# unit-testing session nhibernate

我正在尝试通过NHibernate测试一个简单的对象编辑,我得到了一些奇怪的结果。

我有这个类将标记对象映射为树:

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

做一个简单的测试:

        using (IUnitOfWork uow = new UnitOfWork())
        {
            uow.Start();
            uow.TagRepository.Create(Tag);
            uow.Commit();
            uow.End();

            // Act
            Tag.remove(Tag.Children.First());

            uow.Start();
            uow.TagRepository.Update(Tag);
            uow.Commit();
            uow.End();

            uow.Start();
            TagActual = uow.TagRepository.GetById(Tag.Id);

            //Assert
            TagActual.ShouldBeEquivalentTo(Tag);
            uow.End();
        }

我收到此错误:

NHibernate.HibernateException : changed an immutable collection instance: [Gedi.Domain.Object.Entity.Tag.Children#21]

当我在单个会话中运行测试时(没有在操作之间关闭会话),一切顺利,并且没有异常被引发(除了NHibernate不像我想要的那样更新表的事实报告here

需要一些指导,以及解决此问题的步骤。

感谢。

修改

这是有效的方式

        using (IUnitOfWork uow = new UnitOfWork())
        {
            uow.Start();
            uow.TagRepository.Create(Tag);
            uow.Commit();
            Tag.Remove(Tag.Children.First());
            uow.TagRepository.Update(Tag);
            uow.Commit();
            uow.End();

            uow.Start();
            TagActual = uow.TagRepository.GetById(Tag.Id);
            TagActual.ShouldBeEquivalentTo(Tag);
            uow.End();
        }

但我认为在商业代码中我可能需要在会话之外工作,所以我想让它在任何情况下运行。

我编辑了一些方法名称,因为我没有在数据访问层之外公开会话和会话概念,因为会话是特定的NHibernate

编辑2:

这也很好用:

using (IUnitOfWork uow = new UnitOfWork())
        {
            uow.Start();
            uow.TagRepository.Create(Tag);
            uow.Commit();
            uow.End();

            // Act
            Tag.Description = "EDITED";

            uow.Start();
            uow.TagRepository.Update(Tag);
            uow.Commit();
            uow.End();

            uow.Start();
            TagActual = uow.TagRepository.GetById(Tag.Id);

            //Assert
            TagActual.ShouldBeEquivalentTo(Tag);
            uow.End();
        }

只有该集合在会话外提供错误

1 个答案:

答案 0 :(得分:0)

我看到了一些选项

  • 使用单个会话并检查是否有办法执行会话flush以将更改保留到数据库。

  • 使用单个会话但添加事务,然后在Act之前提交以保留更改。

  • 使用合并将元素附加到其他会话session.Merge(Tag)

  • 在您打开的每个新会话中从数据库中获取元素,而不是使用相同的实例