Sql server 将SQL Server 2008地理类型与nHibernate';s CreateSQLQuery
我试图用nHibernate(2.0.1GA)发出一个SQL更新语句,如下所示:Sql server 将SQL Server 2008地理类型与nHibernate';s CreateSQLQuery,sql-server,nhibernate,Sql Server,Nhibernate,我试图用nHibernate(2.0.1GA)发出一个SQL更新语句,如下所示: 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(); 但是,我收到以下错误:'geog
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的上下文中做到这一点,有什么想法吗?“{whatever}不是公认的内置函数名”是一条SQL Server错误消息,不确定Hibernate在那里做什么,但SQL Server是抱怨它的人。我很确定我可以告诉您发生了什么,但我不知道是否有修复方法 我认为问题在于,NHibernate使用“:”字符来创建命名参数。您的表达式将更改为:
set nocount on;update myusers set geo=geography@p0({0}, {1}, 4326) where userid={2};
@p0将是一个SQL变量。不幸的是,我找不到任何用于转义冒号的文档,因此它们没有被视为命名参数
如果存在转义字符(我对NHibernate源代码的快速浏览没有找到转义字符;如果您想花更多的时间搜索,命名参数将在NHibernate.Engine.Query.ParameterParser中处理),那么您可以使用它
其他解决办法:
- 向源添加转义字符。然后可以使用NHibernate的修改版本。如果你这样做了,你应该向团队提交你的补丁,这样它就可以包含在真实的东西中,而不必维护源代码的修改版本(没有乐趣)
- 在数据库中创建一个用户定义的函数,该函数返回一个geography::Point,然后调用您的函数,而不是标准的SQL函数。这似乎是最快/最简单的起跑方式,但也有点像创可贴。
- 查看中是否存在允许您以编程方式添加geography::Point()的内容[或编辑该项目的代码以添加一个并将修补程序提交给该团队]
- 存在从varchar到Point的隐式转换
使用NHibernate将地理参数设置为其字符串表示形式
使用命名参数定义SQL查询模板
loc
:
const string Query = @"SELECT {location.*}
FROM {location}
WHERE {location}.STDistance(:loc) is not null
ORDER BY {location}.STDistance(:loc)";
将参数设置为点的字符串表示形式:
return session
.CreateSQLQuery(Query)
.AddEntity("location", typeof (Location))
.SetString("loc", "Point (53.39006999999999 -3.0084007)")
.SetMaxResults(1)
.UniqueResult<Location>();
返回会话
.CreateSQLQuery(查询)
.附录(“位置”,类型(位置))
.SetString(“loc”,“点(53.3900699999999-3.0084007)”)
.SetMaxResults(1)
.UniqueResult();
这是供选择的。但是我看不出为什么它不能用于插入或更新。根据@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);
NH很高兴这个问题在源代码中得到解决了吗?我遇到了同样的问题。