如何使用nHibernate不使用nHibernate空间将PostGis几何列映射为wkt

时间:2013-05-08 09:41:44

标签: nhibernate postgis

我需要使用nHibernate读取postgis几何列作为wkt。我知道我可以使用nHibernate Spatial,但在我的情况下这不是一个选项。

我看过这篇文章:Best way to map a hidden property in NHibernate (fluent)其中wkt存储在另一列中,他使用触发器来更新实际的几何体。但是,项目所有者不希望为此目的添加额外的列。

我也找到了这个帖子:Use PostGIS columns transparently in Hibernate,但没有提供答案。

我相信我需要写一个自定义类型,但我真的需要有人指出我正确的方向。我之前没有使用过Postgresql / postgis。

日Thnx!

2 个答案:

答案 0 :(得分:0)

如果您不想要额外的列,您可以创建一个视图,该视图将使用函数从原始表中提取数据,并在视图上创建一个而不是触发器来更新真实表。

答案 1 :(得分:0)

我通过使用nHibernates sql-interceptor解决了这个问题。不是最强大的解决方案,但这样我可以为PostGis和Oracle提供不同的拦截器。

我还研究了nHibernate.Spatial及其几何类型。但我不想使用NetTopologySuite,因此我应该需要编写更多代码。

以下是代码的一部分:

public class PostGisGeometrySqlInterceptor : IInterceptor
{
   ...

    /// <summary>
    /// Modifies all the select statements with geometry so that 
    /// xxx.geometry -> ST_AsText(xxx.geometry)
    /// </summary>
    /// <param name="sql">The original sql string.</param>
    /// <returns>The modified sql string.</returns>
    /// <remarks>
    /// All the geometry fields must be called 'geometry'. 
    /// Works only for one geometry in the sql string.
    /// </remarks>
    public virtual SqlString OnPrepareStatement(SqlString sql)
    {
        if (sql.StartsWithCaseInsensitive("SELECT") && sql.ToString().Contains("geometry"))
        {
            var indexOfGeometry = sql.IndexOfCaseInsensitive("geometry");
            var indexOfSpace = sql.Substring(0, indexOfGeometry).LastIndexOfCaseInsensitive(" ") + 1;

            var oldValue = sql.ToString(indexOfSpace, indexOfGeometry - indexOfSpace + "geometry".Length);
            var newValue = string.Format("ST_AsText({0})", oldValue);
            sql = sql.Replace(oldValue, newValue);
        }
        else if(...)

        ...

        return sql;   
    }