2008-10-26 37 views
2

我想發出一個SQL更新語句與NHibernate(2.0.1GA)是這樣的:使用SQL Server 2008中地理類型與NHibernate的CreateSQLQuery

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(); 

不過,我收到以下錯誤: '地理學@ P0'不是公認的內置函數名稱。

我以爲CreateSQLQuery只會傳遞我給它的SQL並執行它......猜不到。關於如何在nHibernate的環境中做到這一點的任何想法?

+0

這個問題是否曾經在源代碼中得到解決è?我遇到了同樣的問題。 – roryf 2010-03-23 11:25:46

回答

4

我很確定我可以告訴你發生了什麼,但我不知道是否有修復。

我認爲問題在於NHibernate使用':'字符來創建一個命名參數。您的表情變爲:

set nocount on;update myusers set [email protected]({0}, {1}, 4326) where userid={2}; 

而@ p0將成爲SQL變量。不幸的是,我找不到任何逃離冒號的文檔,因此它們不被視爲命名參數。

如果存在轉義字符(我的NHibernate源代碼快速瀏覽沒有找到;如果您想花費更多時間搜索,那麼在NHibernate.Engine.Query.ParameterParser中處理命名參數),那麼您可以使用它。

其他的解決方案:

  • 添加一個轉義字符的來源。然後你可以使用NHibernate的修改版本。如果你這樣做,你應該將你的補丁提交給團隊,以便它可以包含在真實的東西中,而且你不必維護源代碼的修改版本(沒有趣味)。
  • 在您的數據庫中創建一個返回geography :: Point的用戶定義函數,然後調用您的函數而不是標準的SQL函數。這似乎是最快/最簡單的起跑方式,但也有點像創可貼。
  • 看看NHibernate Spatial中是否有東西可讓您以編程方式添加geography :: Point()[或編輯該項目的代碼以添加一個並將修補程序提交給該團隊]。
0

「{whatever}不是公認的內置函數名」是一個SQL Server錯誤消息,不確定Hibernate在那裏做什麼,但SQL Server是一個抱怨它的人。

0

有一個從varchar到Point的隱式轉換。

使用的NHibernate的地形參數設置爲它們的字符串表示

定義與命名放慢參數loc一個SQL查詢模板:

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>(); 

這是一個選擇。但我看不出爲什麼它不適用於插入或更新。

0

繼@克里斯的答案,這裏是一個複製和粘貼的解決方案:

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很高興

相關問題