我今天阅读了一篇关于如何使用 PersistenceSpecification 类测试 Fluent NHibernate 映射的博文。似乎是一个非常好的主意,所以我尝试了一下。但是,在检查 HasMany 关系时,它会不断抛出 System.ArgumentOutOfRangeException。我们使用 SQL Lite 内存数据库进行测试。
这是我的模型的样子。我剪掉了一些不相关的属性等:
public class Area
{
public virtual int AreaId{ get; set; }
public virtual IList<AreaPolygonVertex> Vertices { get; set; }
...
}
public class AreaPolygonVertex
{
public virtual Point Point { get; set; }
public virtual int VertexNumber { get; set; }
public virtual int AreaId { get; set; }
}
public class Point
{
public double X {get; set;}
public double Y {get; set;}
}
以下是 NHibernate 映射:
public class AreaMap : ClassMap<Area>
{
public AreaMap()
{
Table("VIEW_AREAS");
Id(x => x.AreaId, "ID");
HasMany(x => x.Vertices).KeyColumn("AREA_ID");
...
}
}
public class AreaPolygonVertexMap : ClassMap<AreaPolygonVertex>
{
public AreaPolygonVertexMap()
{
Table("AREA_POLYGON_VERTICES");
CompositeId()
.KeyProperty(x => x.AreaId, "AREA_ID")
.KeyProperty(x => x.VertexNumber, "VERTEX_NO");
Component(x => x.Point, m =>
{
m.Map(x => x.X, "X");
m.Map(x => x.Y, "Y");
});
Map(x => x.VertexNumber, "VERTEX_NO");
Map(x => x.AreaId, "AREA_ID");
}
}
最后是测试:
[Test]
public void should_map_areas_correctly()
{
var vertex = new AreaPolygonVertex {
AreaId = 1,
Point = new Point(20, 30),
VertexNumber = 1
};
_session.Save(vertex);
new PersistenceSpecification<Area>(_session)
.CheckProperty(c => c.AreaId, 1)
.CheckList(c => c.Vertices, new List<AreaPolygonVertex>{ vertex })
.VerifyTheMappings();
}
这会引发 ArgumentOutOfRangeException,说“索引超出范围。必须为非负数且小于集合的大小。参数名称:索引”。在这个异常中似乎没有更多有用的信息。
起初我在运行验证调用之前没有执行 _session.Save(vertex) ,但我发现在有这样的 HasMany 关系时必须手动将“子对象”插入 _session 中。不过,可能不适合我的确切情况。
PS:映射和模型已经针对真实(oracle)数据库进行了测试,它们应该可以正常工作(至少对于读取数据)。我也使用 CheckComponentList 而不是 CheckList 进行了测试,但结果仍然相同。如果我删除“.CheckList(..”行,而只是检查所有其他属性,它工作正常。
如果我在这里做错了什么,希望有人能启发我。如前所述,这是我的第一个 NHibernate 映射测试,所以要温柔 =)