Sql server 将SQL Server 2008地理类型与nHibernate';s CreateSQLQuery

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

我试图用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();
但是,我收到以下错误:'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很高兴

      这个问题在源代码中得到解决了吗?我遇到了同样的问题。