Подтвердить что ты не робот

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 для использования типов пространственной географии, которые могли бы предоставить любую информацию, будет с благодарностью.

4b9b3361

Ответ 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".

Просто провел целую ночь, поняв, что один из них.