将NHibernate 3 linq提供程序与NHibernate spatial一起使用
我开始与NHibernate 3 linq提供商合作,这很好。 到目前为止,我一直使用NHibernate spatial标准 如何将linq与NHibernate结合使用 谢谢,将NHibernate 3 linq提供程序与NHibernate spatial一起使用,linq,nhibernate,spatial,Linq,Nhibernate,Spatial,我开始与NHibernate 3 linq提供商合作,这很好。 到目前为止,我一直使用NHibernate spatial标准 如何将linq与NHibernate结合使用 谢谢, 罗恩我不知道这是否是现成的。要么使用linq提供程序中的NH钩子来实现它,要么像我在这里发布的那样执行它自从您最初发布问题以来,已经过了一段时间,但由于您没有将其标记为已回答,所以让我向您展示我在这个主题上写的一篇博客文章,其中展示了在HQL和linq中使用NH Spatial的几个查询示例 您可以检查它,但可以在L
罗恩我不知道这是否是现成的。要么使用linq提供程序中的NH钩子来实现它,要么像我在这里发布的那样执行它自从您最初发布问题以来,已经过了一段时间,但由于您没有将其标记为已回答,所以让我向您展示我在这个主题上写的一篇博客文章,其中展示了在HQL和linq中使用NH Spatial的几个查询示例
您可以检查它,但可以在LINQ查询中使用NHibernate.Spatial。您必须使用一个NHibernate.Spatial分叉(例如:这里是@psousa的分叉:或者这里是@suryapratap的分叉) 通过查看NHibernate.Spatial.Linq.Functions.spatiallinqtohqlngeneratorregistry中的源代码,可以猜测支持的操作范围 源文件。例如,下面的代码:
public class AnalysisDistanceGenerator : SpatialMethodGenerator<IGeometry, double>
{
public AnalysisDistanceGenerator() : base(g => g.Distance(null)) { }
}
之所以会出现这种情况,是因为NHibernate试图找到一个NHibernate IType实例,用于将“点”数据类型(参数)转换为SQL,但最终没有找到任何内容,因此它使用默认的SerializableType,它不尊重您在点实例本身上设置的SRID参数
疏忽之处在于,NHibernate本身不允许在其自身注册的默认持久器之外指定“实体持久器”(充当从/到SQL的类型转换器)。对于加载或保存实体,它使用为从类映射(hbm/xml、fluent或代码映射)编译的实体定义的元数据,这样可以工作,但对于未映射的点实例,它只是错误地处理它们
在NHibernate中花费数小时进行调试后,解决方案就是通过为NHibernate注册IType(然后您可以为其定义SRID、子类型),使NHibernate将Point和IPoint实例当作内置类型来处理,并且工作正常
不幸的是,此方法使用反射来访问标记为private的NHibernate.Type.TypeFactory.RegisterType方法。我找不到任何公共API来实现此方法
只需在创建NHibernate SessionFactory(应用程序内启动)期间调用此方法一次。显然,它假设您将对所有未显式设置SRID的点参数使用默认SRID4326。如果需要,可以为参数字典传递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 }
});
}
静态无效注册表GeometryTypeForIpIntusingReflection()
{
var方法=
typeof(TypeFactory).GetMethods(BindingFlags.NonPublic | BindingFlags.Static);
var requiredOverload=方法。其中(
x=>
{
如果(x.Name!=“RegisterType”)返回false;
var args=x.GetParameters();
如果(args.Length!=2)返回false;
返回参数[0]。参数类型==typeof(IType)
&&args[1]。参数类型==typeof(IEnumerable);
})
.FirstOrDefault();
if(requiredOverload==null)
{
抛出新的NotSupportedException(
“在NHibernate中找不到TypeFactory.RegisterType方法重载。请报告此问题。”);
}
requiredOverload.Invoke(
无效的
新对象[]
{
新客户类型(
类型(几何类型),
新词典
{
{“srid”,“4326”},
{“子类型”,“点”}
}),
新[]
{typeof(IPoint).AssemblyQualifiedName,typeof(Point).AssemblyQualifiedName}
});
}
我无法让它工作。我在创建会话工厂时调用了该方法,但随后出现了一个不同的运行时错误。
ArgumentException: 24204: The spatial reference identifier (SRID) is not valid.
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 }
});
}