NHibernate.Spatial和Sql 2008地理类型 – 如何配置

我试图使用Nhibernate与Sql 2008地理类型,并有困难。 我正在使用Fluent Nhibernate来配置我相当新的,所以这也可能是问题。

首先,我试图坚持的课程看起来像:

public class LocationLog : FluentNHibernate.Data.Entity { public virtual new int Id {get;set;} public virtual DateTime TimeStamp {get;set;} public virtual GisSharpBlog.NetTopologySuite.Geometries.Point Location {get;set;} } 

映射类如下所示:

 public class LocationLogMap : ClassMap { ImportType(); Id(x => x.Id); Map(x => x.TimeStamp).Generated.Insert(); Map(x => x.Location); } 

为了将MsSql2008GeographyDialect与Fluent Nhibernate一起使用,我创建了自己的配置类:

 public class Sql2008Configuration : PersistenceConfiguration { public Sql2008Configuration() { Driver(); } public static Sql2008Configuration MsSql2008 { get { return new Sql2008Configuration().Dialect(); } } } 

所以我有配置代码,如:

 var configuration = Fluently.Configure() .Database(Sql2008Configuration.MsSql2008.ConnectionString(c => c.Is(connectionString))) .Mappings(m => m.FluentMappings .AddFromAssemblyOf() ); 

所有这些都设置了这样一个事实,即我在尝试将LocationLog类型持久化到数据库时收到以下错误:

执行用户定义的例程或聚合“geography”期间发生.NET Framework错误:System.ArgumentException:24204:空间参考标识符(SRID)无效。 指定的SRID必须与sys.spatial_reference_systems目录视图中显示的受支持的SRID之一匹配。 System.ArgumentException:在Microsoft.SqlServer.Types.SqlGeography.set_Srid(Int32值)的Microsoft.SqlServer.Types.SqlGeography.Read(BinaryReader r)at SqlGeography ::。DeserializeValidate(IntPtr,Int32,CClrLobContext *)

我已经阅读了以下有关如何配置和使用Nhibernate Spatial库的文章:

  • http://nhibernate.info/doc/spatial/configuration-and-mapping.html
  • http://nhibernate.info/doc/spatial/sample-usage.html

但似乎都没有帮助。 任何有经验配置Nhibernate使用可以提供任何见解的空间地理类型的人都将非常感激。

我在同一条船上,多亏了你的开始,我得到它的工作(插入和读取空间数据)。 对于其他感兴趣的人,首先是GisSharpBlog.NetTopologySuite.Geometries.Point类在NetTopologySuite.dll中,它是nHibernate.Spatial下载的一部分。

其次,根据James的观点,确保将SRID设置为4326。

最后,地图需要如下所示:

 Map(a => a.Location).CustomType(typeof(NHibernate.Spatial.Type.GeometryType)); 

我正在使用地理,但我在某处读到使用GeometryType可能会起作用,它对我有效(我插入了一些点并在数据库中validation了它)。 我还读到最好为地理编写SQL Query,以便您可以使用特殊的SQL 2008 Spatial方法(而不是使用Criteria)。

史蒂夫是对的,您需要为几何类型显式设置SRID 。 查看NHibernate.Spatial源(您可以使用SVN或其他任何方式签出),搜索SRID会在代码中隐藏起来作为注释提示:

    1234    

看起来您需要将名为SRID的参数设置为您需要的任何数字(在SRID表中查找)。 显然这是老式的XML配置,但是流畅的将有一个方法来添加键/值字符串参数。 试一试。


编辑

经过一番研究后,我发现尝试在列上设置srid属性失败了NHibernate的XML映射validation,它抛出了一个XmlSchemaValidationException。 相反,我发现NetNopologySuite中的几何类型在对象本身上具有SRID属性,并且设置这使得工作正常。 例如

 LocationLog log = new LocationLog { Location = new Point() }; log.Location.SRID = 4326; Session.Save(log); 

必须有一个更好的方法来做到这一点(配置它而不是一直设置它)但我还没有这样做。 如果您查看MsSql2008GeometryType类,它有一个名为SetDefaultSRID(IGeometry)的受保护方法 – 它必须在那里是有原因的!

不是答案,而是问题;-)

  • 您是否在GisSharpBlog.NetTopologySuite.Geometries.Point对象上设置SRID?

默认(因为该点是几何)是0并且在尝试将LocationLog.Location属性保持为地理位置时会出现SQL错误。 0不是sql地理字段的有效SRID。 您需要在sys.spatial_reference_systems视图中指定一个。

  • 你试过没有Fluent NHibernate吗?

从问题中消除尽可能多的组件。

您可以使用默认SRID创建自己的工厂。 例如,您可以为工厂创建一个Facade,如下所示:

 public static class Default { private const int DefaultSrid = 4326; public static readonly IGeometryFactory Factory; static Default() { Factory = new GeometryFactory(new PrecisionModel(), DefaultSrid); } } 

并像这样使用它:

 var point = Default.Factory.CreatePoint(new Coordinate(10, 10)); 

而不是使用“新”关键字。 您还可以在IoC框架中将Default.Factory用作工厂方法,以创建没有默认外观的新几何。

我知道这几乎没用,但无论如何。 实现之后所有lain都说过在你的HQL查询中使用SetParameter第三个IType参数。 含义

  Hero hero = openSession.Get(3); openSession.CreateQuery( "from Hero h where NHSP.Distance(h.Location,:thislocation)<1000" ).SetParameter("thislocation", hero.Location, new CustomType(typeof(MsSql2008GeographyType), null) ).SetResultTransformer(new DistinctRootEntityResultTransformer()) .List(); 

必须传递新的CustomType(typeof(MsSql2008GeographyType),null),否则你会得到你太熟悉的“System.ArgumentException:24204”。

只花了一整夜才搞清楚那一个。