2012-03-08 34 views

回答

0

自你最初發布問題以來已經過去了一段時間,但是,因爲你沒有標記爲回答,所以讓我給你看一個我寫過關於這個主題的博客文章,展示了在HQL和LINQ中使用NH Spatial的幾個查詢示例。

你可以檢查一下here

0

晚的答案,但肯定的,你可以在LINQ查詢使用NHibernate.Spatial。您必須使用NHibernate.Spatial分支之一(例如:@psousa這裏的:https://github.com/pmcxs/Nhibernate.Spatial或@suryapratap這裏的https://github.com/suryapratap/Nhibernate.Spatial)。

支持的操作範圍可以通過查看源代碼在NHibernate.Spatial.Linq.Functions.SpatialLinqToHqlGeneratorsRegistry 源文件中找到。例如這個代碼在這裏:

public class AnalysisDistanceGenerator : SpatialMethodGenerator<IGeometry, double> 
{ 
    public AnalysisDistanceGenerator() : base(g => g.Distance(null)) { } 
} 

這意味着你應該能夠做到這樣的查詢:

dbSession.Query<Entity>().Where(x => x.Location.Distance(point) < 50).FirstOrDefault(); 

有一個錯誤(或實際上,它是在NHibernate的設計監督)導致像上面的查詢需要一個Point實例失敗,錯誤:

ArgumentException: 24204: The spatial reference identifier (SRID) is not valid. 

這是因爲NHibernate的嘗試找到一個NHibernate的ITYPE實例使用coverting「點」數據典型值e(參數)轉換爲SQL並最終找不到任何內容,因此它使用默認的SerializableType,它不尊重您在點實例本身上設置的SRID參數。

監督是NHibernate本身不允許指定「實體持久化」(作爲從/到SQL的類型轉換器)超出它自帶的默認值。對於加載或保存實體,它使用爲從類映射(hbm/xml,fluent或通過代碼映射)編譯的實體定義的元數據,這樣可以工作,但對於非映射Point實例,它只是處理它們錯誤。

在NHibernate中花費了很多小時的調試之後,解決方案只是簡單地讓NHibernate處理Point和IPoint實例,就好像它們是內置類型一樣,方法是爲它註冊一個IType(然後可以爲它定義SRID,子類型),它工作正常。

不幸的是,這個方法使用反射來訪問標記爲private的NHibernate.Type.TypeFactory.RegisterType方法。我無法找到任何公共API來實現此方法。

只需在創建NHibernate SessionFactory時(​​在應用程序啓動時)調用此方法一次。顯然,它假設您將對所有未明確設置其SRID的點參數使用默認SRID 4326。您可以傳遞null作爲參數字典,而不是指定默認的SRID和子類型(如果需要)。

這是醜陋的,但完美的作品:

static void RegisterGeometryTypeForIPointUsingReflection() 
    { 
     var methods = 
      typeof(TypeFactory).GetMethods(BindingFlags.NonPublic | BindingFlags.Static); 

     var requiredOverload = methods.Where(
      x => 
      { 
       if (x.Name != "RegisterType") return false; 

       var args = x.GetParameters(); 
       if (args.Length != 2) return false; 

       return args[0].ParameterType == typeof(IType) 
         && args[1].ParameterType == typeof(IEnumerable<string>); 
      }) 
      .FirstOrDefault(); 

     if (requiredOverload == null) 
     { 
      throw new NotSupportedException(
       "Could not find TypeFactory.RegisterType method overload in NHibernate. Please report this issue."); 
     } 

     requiredOverload.Invoke(
      null, 
      new object[] 
      { 
       new CustomType(
        typeof(GeometryType), 
        new Dictionary<string, string> 
        { 
         { "srid", "4326" }, 
         { "subtype", "POINT" } 
        }), 
       new[] 
       { typeof(IPoint).AssemblyQualifiedName, typeof(Point).AssemblyQualifiedName } 
      }); 
    } 
+1

我不能得到這個工作。我在創建會話工廠時調用了該方法,但隨後出現了不同的運行時錯誤。 – nfplee 2014-06-12 08:51:33

相關問題