我正在尝试通过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();
}
只有该集合在会话外提供错误
答案 0 :(得分:0)
我看到了一些选项
使用单个会话并检查是否有办法执行会话flush
以将更改保留到数据库。
使用单个会话但添加事务,然后在Act
之前提交以保留更改。
使用合并将元素附加到其他会话session.Merge(Tag)
在您打开的每个新会话中从数据库中获取元素,而不是使用相同的实例