【问题标题】:NHibernate, update read only collection outside of Session (changed an immutable collection instance)NHibernate,在 Session 之外更新只读集合(更改了不可变集合实例)
【发布时间】:2014-10-05 12:27:53
【问题描述】:

我正在尝试通过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 没有按照我报告的那样更新表格@ 987654321@)

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

谢谢。

编辑

这是行之有效的方式

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

只有集合在会话之外给出错误

【问题讨论】:

    标签: c# unit-testing session nhibernate


    【解决方案1】:

    我看到了一些选项

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

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

    • 使用合并将元素附加到不同的会话 session.Merge(Tag)

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

    【讨论】:

    • 感谢您的回答。在我的 Uow 中,开始创建会话和事务,提交很明显,结束关闭会话。关于您的想法,请参阅我的更新
    • @gt.guybrush:实例属于一个会话,所以你需要做一些事情,所以在另一个会话上使用它。通常,您的会话范围足够长,可以避免处理多会话问题。如果它是一个 Web 应用程序,会话通常是每个请求的,因此在非常奇怪的情况下,您必须处理跨会话问题。您是否测试了 session.Merge(Tag) 以将实例附加到不同的会话?
    • 我不公开会话,所以我不能使用合并。此时我可以使用我发布的编辑。我只是希望能够毫无问题地从会话中锻炼出来。我认为奇怪的是,除了集合之外,一切都正常。附言虽然我们是你能帮我解决我上面链接的相关问题吗? (stackoverflow.com/questions/25261562/…)
    猜你喜欢
    • 1970-01-01
    • 2013-11-03
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多