我开始使用NHibernate 3 linq提供商,这很棒。 到目前为止,我已经将NHibernate空间与Criteria一起使用。
如何在NHibernate空间中使用linq?
谢谢, 罗恩
答案 0 :(得分:0)
我不知道是否可以开箱即用。要么在linq提供程序中使用NH钩子来实现它,要么就像我在这里发布https://stackoverflow.com/a/9585622/671619
一样答案 1 :(得分:0)
自从您最初发布问题以来已经过了一段时间,但是,由于您没有将其标记为已回答,请让我向您展示我在该主题上撰写的博文,在HQL中使用NH Spatial显示几个查询示例和LINQ。
您可以查看here
答案 2 :(得分:0)
迟到的回答但是,您可以在LINQ查询中使用NHibernate.Spatial。你必须使用NHibernate.Spatial forks之一(例如:@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实例用于将“Point”数据类型(参数)转换为SQL并最终找不到任何内容,因此它使用不遵循SRID参数的默认SerializableType你在点实例上设置了它。
监督是NHibernate本身不允许在其自身注册的默认值之外指定“实体持久性”(作为SQL的类型转换器)。对于加载或保存实体,它使用为从类映射(hbm / xml,fluent或代码映射)编译的实体定义的元数据,因此可以工作,但对于非映射的Point实例,它只是处理它们错误
在NHibernate上花了很多时间调试之后,解决方案只是让NHibernate通过为它注册一个IType来处理Point和IPoint实例,就好像它们是内置类型一样(然后你可以为它定义SRID,子类型)它工作正常。
不幸的是,此方法使用反射来访问标记为private的NHibernate.Type.TypeFactory.RegisterType方法。我无法找到任何公共API来实现此方法。
在创建NHibernate SessionFactory期间(在app启动时)调用此方法一次。显然,它假设您将对未明确设置其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 }
});
}