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<LocationLog>
{
ImportType<GisSharpBlog.NetTopologySuite.Geometries.Point>();
Id(x => x.Id);
Map(x => x.TimeStamp).Generated.Insert();
Map(x => x.Location);
}
Чтобы использовать MsSql2008GeographyDialect с Fluent Nhibernate, я создал свой собственный класс конфигурации:
public class Sql2008Configuration
: PersistenceConfiguration<Sql2008Configuration, MsSqlConnectionStringBuilder>
{
public Sql2008Configuration()
{
Driver<SqlClientDriver>();
}
public static Sql2008Configuration MsSql2008
{
get { return new Sql2008Configuration().Dialect<MsSql2008GeographyDialect>(); }
}
}
поэтому у меня есть код конфигурации, например:
var configuration = Fluently.Configure()
.Database(Sql2008Configuration.MsSql2008.ConnectionString(c => c.Is(connectionString)))
.Mappings(m => m.FluentMappings
.AddFromAssemblyOf<LocationLog>()
);
Все это для установки факта, что я получаю следующую ошибку при попытке сохранить тип LocationLog в базе данных:
Ошибка .NET Framework произошла во время выполнение пользовательской программы или совокупная "география": System.ArgumentException: 24204: идентификатор пространственной привязки (SRID) недействительно. Указанный SRID должен соответствовать одному из поддерживаемых SRID отображается в Каталог sys.spatial_reference_systems Посмотреть. Исправление System.ArgumentException: at Microsoft.SqlServer.Types.SqlGeography.set_Srid (Int32 значение) при Microsoft.SqlServer.Types.SqlGeography.Read(BinaryReader r) при SqlGeography::. DeserializeValidate (IntPtr, Int32, CClrLobContext *)
Я прочитал следующие статьи о том, как настроить и использовать библиотеки Nhibernate Spatial:
но ничто не помогает. Любой, у кого есть опыт настройки Nhibernate для использования типов пространственной географии, которые могли бы предоставить любую информацию, будет с благодарностью.
Ответы
Ответ 1
Я нахожусь в одной лодке, и благодаря вашему старту я получил ее работу (вставка и чтение пространственных данных). Для кого-либо, кого это интересует, сначала класс GisSharpBlog.NetTopologySuite.Geometries.Point находится в NetTopologySuite.dll, который является частью загрузки nHibernate.Spatial.
Во-вторых, в соответствии с точкой Джеймса, убедитесь, что SRID установлен на 4326.
И, наконец, карта должна выглядеть так:
Map(a => a.Location).CustomType(typeof(NHibernate.Spatial.Type.GeometryType));
Я использую Географию, но где-то я читал, что использование GeometryType может работать, и это для меня (я вставил некоторые точки и проверил их в базе данных). Я также прочитал, что лучше всего написать SQL Query for Geography, чтобы вы могли использовать специальные методы Spatial SQL 2008 (в отличие от использования критериев).
Ответ 2
Стив прав, вам нужно явно установить SRID для вашего типа геометрии. Глядя на источник NHibernate.Spatial(который вы можете проверить с помощью SVN или что-то еще), выполнение поиска для SRID придумывает это в коде как подсказку комментария:
<class name="MyGeoTableA">
<property name="MyGeoColumn">
<type name="NHibernate.Spatial.Type.GeometryType, NHibernate.Spatial">
<param name="srid">1234</param>
</type>
</property>
</class>
Похоже, вам нужно установить параметр SRID на любой номер, который вам нужен (посмотрите его в таблице SRID), Очевидно, что это конфигурация XML старой школы, но у свободно будет способ где-то добавить параметры строки ключа/значения. Попробуйте.
Edit
После немного большего количества исследований я обнаружил, что попытка установить атрибут srid в столбце не прошла проверку NHibernate XML mapping, он выдает исключение XmlSchemaValidationException. Вместо этого я обнаружил, что типы геометрии в NetNopologySuite имеют атрибут SRID для самого объекта, и установка этого делает работу. например.
LocationLog log = new LocationLog { Location = new Point() };
log.Location.SRID = 4326;
Session.Save(log);
Должен быть лучший способ сделать это (настроить его, а не устанавливать его все время), но я еще не работал. Если вы заглянете в класс MsSql2008GeometryType, у него есть защищенный метод SetDefaultSRID (IGeometry) - он должен быть там по какой-то причине!
Ответ 3
Не совсем ответ, но вопросы; -)
- Вы устанавливаете SRID в объекте GisSharpBlog.NetTopologySuite.Geometries.Point?
По умолчанию (поскольку точка является геометрией) равна 0 и даст вам ошибку SQL при попытке сохранить свойство LocationLog.Location в качестве географии. 0 не является допустимым SRID для полей географии sql. Вам нужно будет указать один из представления sys.spatial_reference_systems.
- Вы пробовали без Fluent NHibernate?
Чтобы устранить так много компонентов из проблемы.
Ответ 4
Вы можете создать свой собственный factory с SRID по умолчанию.
Например, вы можете создать фасад для таких фабрик, как:
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));
вместо того, чтобы использовать "новое" ключевое слово.
Вы также можете использовать метод Default.Factory как метод factory в своей инфраструктуре IoC для создания новых геометрий без фасада по умолчанию.
Ответ 5
Я знаю, что это вряд ли будет полезно, но в любом случае.
После того, как все Lain сказал, что вы используете в своих запросах HQL SetParameter третий параметр IType. Значение в
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();
новый CustomType (typeof (MsSql2008GeographyType), null) должен быть передан или вы получите слишком много знакомых "System.ArgumentException: 24204".
Просто провел целую ночь, поняв, что один из них.