I am trying to use Nhibernate with the Sql 2008 Geography type and am having difficulty. I am using Fluent Nhibernate to configure which I am fairly new to so that may be th
I know this hardly be useful but in any case. After implementing all lain had said do use in your HQL queries SetParameter third IType parameter. Meaning in
Hero hero = openSession.Get<Hero>(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();
new CustomType(typeof(MsSql2008GeographyType), null) must be passed or you get your all too famililar "System.ArgumentException: 24204".
Just spent whole night figuring that one out.
Not really an answer but questions ;-)
The default (since the point is a geometry) is 0 and will give you a SQL error when trying to persist the LocationLog.Location property as a geography. 0 is not a valid SRID for sql geography fields. You will need to specify one from the sys.spatial_reference_systems view.
To eliminate as many components from the problem.
I am in the same boat, and thanks to your start I got it working (inserting and reading spatial data). For anyone else who is interested, firstly the GisSharpBlog.NetTopologySuite.Geometries.Point class is in NetTopologySuite.dll which is part of the nHibernate.Spatial download.
Secondly, as per James point, make sure you set the SRID to 4326.
And lastly, the map needs to look like this:
Map(a => a.Location).CustomType(typeof(NHibernate.Spatial.Type.GeometryType));
I am using Geography, but I read somewhere that using GeometryType may work and it does for me (I inserted some points and verified it in the database). I also read that its best to write SQL Query's for Geography so that you can use the special SQL 2008 Spatial methods (as opposed to using Criteria).
Steve is right, you need to explicitly set a SRID for your geometry type. Looking at the NHibernate.Spatial source (which you can checkout using SVN or whatever), doing a search for SRID comes up with this buried in the code as a comment hint:
<class name="MyGeoTableA">
<property name="MyGeoColumn">
<type name="NHibernate.Spatial.Type.GeometryType, NHibernate.Spatial">
<param name="srid">1234</param>
</type>
</property>
</class>
It looks like you need to set a parameter named SRID to whatever number you need (look it up in a SRID table). Obviously this is old-school XML configuration but fluent will have a method somewhere to add key/value string parameters. Give that a try.
Edit
After a bit more research, I found that trying to set a srid attribute on a column failed NHibernate's XML mapping validation, it throws an XmlSchemaValidationException. Instead, I found that geometry types in NetNopologySuite have a SRID attribute on the object themselves, and setting this makes things work. e.g.
LocationLog log = new LocationLog { Location = new Point() };
log.Location.SRID = 4326;
Session.Save(log);
There must be a better way to do this though (configure it instead of setting it all the time) but I haven't worked that out yet. If you look inside MsSql2008GeometryType class, it has a protected method called SetDefaultSRID(IGeometry) - it must be there for a reason!
You can create your own factory with a default SRID. For example, you can create a facade for factories such as this:
public static class Default
{
private const int DefaultSrid = 4326;
public static readonly IGeometryFactory Factory;
static Default()
{
Factory = new GeometryFactory(new PrecisionModel(), DefaultSrid);
}
}
and use it like this:
var point = Default.Factory.CreatePoint(new Coordinate(10, 10));
instead of using the "new" keyword. You can also use the Default.Factory as a factory method in your IoC framework to create new geometries without the Default facade.