我使用Spatial.NHibernate将一些几何形状保存到Sql Server 2008中的Geography列。这是我的映射:
public class AreaMapping : ClassMap<Area>
{
public AreaMapping()
{
Id(c => c.Id).GeneratedBy.HiLo(100.ToString());
Map(c => c.Name).Not.Nullable();
Map(x => x.Boundary)
.CustomTypeIs<MsSql2008GeographyType>()
.Not.Nullable()
.CustomSqlTypeIs("GEOGRAPHY");
}
}
映射似乎有效。这是班级:
public class Area
{
public virtual Guid Id { get; set; }
public virtual Polygon Boundary { get; set; }
public virtual string Name { get; set; }
}
然而,当我去保存这样的区域时:
Area area = new Area{ Boundary = new Polygon(new LinearRing(new ICoordinate[]{
new Coordinate(-1.911524, 55.136334),
new Coordinate(-1.912679, 55.136293),
new Coordinate(-1.912689, 55.136178),
new Coordinate(-1.911507, 55.136194),
new Coordinate(-1.911524, 55.136334)}))
Session.Save(area);
我收到以下错误:
指定的输入不代表 一个有效的地理实例。
类型:System.ArgumentException 来源:Microsoft.SqlServer.Types TargetSite: Microsoft.SqlServer.Types.SqlGeography ConstructGeographyFromUserInput(Microsoft.SqlServer.Types.GeoData, Int32)......等等。
据我所知,地理类型的有效多边形必须逆时针绘制,并且必须关闭,并且不得重叠。我很确定我正在履行所有这些限制(如果我错了请纠正我)所以我有点难过。我的多边形有问题,或者NHibernate没有正确地保持它 - 欢迎任何帮助!
修改 好吧,我现在很困惑。
为简化起见,我将多边形更改为:
Area area = new Area{ Boundary = new Polygon(new LinearRing(new ICoordinate[]{
new Coordinate(10,15),
new Coordinate(10,5),
new Coordinate(20,5),
new Coordinate(20,15),
new Coordinate(10,15)}))
我得到了相同的
指定的输入不代表 一个有效的地理实例。
请注意,多边形绘制为逆时针(as it should be according to various sources)。但如果我将坐标改为顺时针:
Area area = new Area{ Boundary = new Polygon(new LinearRing(new ICoordinate[]{
new Coordinate(10,15),
new Coordinate(20,15),
new Coordinate(20,5),
new Coordinate(10,5),
new Coordinate(10,15)}))
似乎没关系。顺便说一下有效还是什么?
答案 0 :(得分:2)
好的,我知道发生了什么事。微软凭借其无限的智慧,似乎违背了整个世界其他地区,并决定在他们的WKT地理坐标表示中,他们将Latitiude放在经度(Y,X)之前。
X,Y?你可能会问WTF?!好吧a whole debate about it,显然他们有他们的理由,但普遍的共识是它很糟糕,所以他们是going to change it。
它太糟糕了,因为它完全打破了互操作性。当NHibernate空间持久存在NetTopologySuite对象时,我用它来保持地理(IGeography类型),它将坐标写为X,Y(我认为它应该工作的自然,预期的方式)。当它击中SQL服务器时,它试图将X解释为Y和Y作为X,因此我的所有问题都是无效类型。
所以现在我要么修复NHibernate,要么交换代码中的坐标。微软感到羞耻,因为给我带来了这样的痛苦!