Использование типов географии SQL Server 2008 с CreateSQLQuery nHibernate

Я пытаюсь выполнить оператор обновления SQL с помощью nHibernate (2.0.1GA) следующим образом:

sqlstring = string.Format("set nocount on;update myusers set geo=geography::Point({0}, {1}, 4326) where userid={2};", mlat, mlong, userid);
_session.CreateSQLQuery(sqlstring).ExecuteUpdate();

Однако я получаю следующую ошибку: «geography@p0» не является распознанным именем встроенной функции.

Я думал, что CreateSQLQuery просто передаст SQL, который я ему дал, и выполнит его... думаю, нет. Любые идеи о том, как я могу это сделать в контексте nHibernate?


person Webjedi    schedule 26.10.2008    source источник
comment
Эта проблема когда-либо была решена в источнике? Я сталкиваюсь с той же проблемой.   -  person roryf    schedule 23.03.2010


Ответы (4)


Я почти уверен, что могу сказать вам, что происходит, но я не знаю, есть ли для этого исправление.

Я думаю, проблема в том, что символ ':' используется NHibernate для создания именованного параметра. Ваше выражение меняется на:

set nocount on;update myusers set geo=geography@p0({0}, {1}, 4326) where userid={2};

А @p0 будет переменной SQL. К сожалению, я не могу найти документацию по экранированию двоеточий, поэтому они не рассматриваются как именованный параметр.

Если escape-символ существует (мой быстрый просмотр исходного кода NHibernate не нашел его; именованные параметры обрабатываются в NHibernate.Engine.Query.ParameterParser, если вы хотите потратить немного больше времени на поиск), вы можете использовать его.

Другие решения:

  • Добавьте escape-символ к источнику. Затем вы можете использовать модифицированную версию NHibernate. Если вы сделаете это, вы должны отправить свой патч команде, чтобы его можно было включить в настоящую версию, и вам не нужно было поддерживать измененную версию исходного кода (неинтересно).
  • Создайте пользовательскую функцию в своей БД, которая возвращает geography::Point, затем вызовите свою функцию вместо стандартной функции SQL. Это кажется самым быстрым/простым способом приступить к работе, но также ощущается как лейкопластырь.
  • Посмотрите, есть ли что-то в NHibernate Spatial, что позволит вам программно добавить географию:: Point() [или отредактируйте код для этого проекта, чтобы добавить его и отправить патч этой команде].
person Chris Shaffer    schedule 16.03.2009

«{whatever} не является распознанным именем встроенной функции» — это сообщение об ошибке SQL Server, не знаю, что там делает Hibernate, но SQL Server жалуется на это.

person tonyz    schedule 14.03.2009

Существует неявное преобразование из varchar в Point.

Используйте NHibernate, чтобы установить географические параметры в их строковое представление.

Определите шаблон SQL-запроса с именованным параметром loc:

const string Query = @"SELECT   {location.*}
FROM     {location}
WHERE    {location}.STDistance(:loc) is not null
ORDER BY {location}.STDistance(:loc)";

Установите параметр в строковое представление Point:

return session
                .CreateSQLQuery(Query)
                .AddEntity("location", typeof (Location))
                .SetString("loc", "Point (53.39006999999999 -3.0084007)")
                .SetMaxResults(1)
                .UniqueResult<Location>();

Это для селекта. но я не вижу причин, по которым это не сработает для вставки или обновления.

person mattk    schedule 06.03.2013

Следуя ответу @Chris, вот решение для копирования и вставки:

CREATE FUNCTION GetPoint 
(
    @lat float,
    @lng float,
    @srid int
)
RETURNS geography
AS
BEGIN

declare @point geography = geography::Point(@lat, @lng, @srid);

RETURN @point

END
GO

что ты делаешь

dbo.GetPoint(@Latitude, @Longitude, 4326)

вместо

geography::Point(@Latitude, @Longitude, 4326);

И НГ доволен

person Yosoyadri    schedule 26.04.2015