NHibernate,更新会话外的只读集合(改变一个不可变集合实例)
本文关键字:集合 一个 不可变 实例 改变 只读 NHibernate 更新 会话 | 更新日期: 2023-09-27 18:17:42
我正试图通过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
没有像我在这里报告的那样更新表)
需要一些指导,以及解决这个问题的步骤。
谢谢。
编辑
这是工作方式
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:
this too works fine:
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();
}
我看到一些选项
-
使用单个会话并检查是否有方法执行会话
flush
以将更改持久化到数据库。 -
使用单个会话但添加事务,然后在
Act
之前提交以持久化您的更改。 -
使用merge将元素附加到不同的会话
session.Merge(Tag)
-
在每次打开新会话时从数据库中获取元素,而不是使用相同的实例