将 LINQ 扩展到 Nhibernate 提供程序,结合动态 LINQ 问题 [英] Extending LINQ to Nhibernate provider, in combination with Dynamic LINQ problem

查看:17
本文介绍了将 LINQ 扩展到 Nhibernate 提供程序,结合动态 LINQ 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 NHibernate 3.1.0 并且我正在尝试通过使用 BaseHqlGeneratorForMethod 并扩展 DefaultLinqToHqlGeneratorsRegistry 来扩展 LINQ 提供程序,如Fabio 的帖子.

例如,为了支持 ToString(),我创建了一个 ToStringGenerator,如下所示.

内部类 ToStringGenerator : BaseHqlGeneratorForMethod{公共 ToStringGenerator(){支持的方法 = 新 []{ReflectionHelper.GetMethodDefinition(x => x.ToString())};}public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitorvisitor){返回 treeBuilder.Cast(visitor.Visit(targetObject).AsExpression(), typeof(string));}}

我已经注册使用

内部类 CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry{公共 CustomLinqToHqlGeneratorsRegistry(){this.Merge(new ToStringGenerator());}}

等等.到目前为止,这适用于静态"查询,我可以这样使用它:

var results = mSession.Query();字符串 pId = "1";结果 = results.Where(p => p.Id.ToString().Contains(pId));

这正确地转换为其对应的 SQL(使用 SQL Server 2008)

 where cast(project0_.Id as NVARCHAR(255)) like (''%''+@p0+''%'')

当我尝试将它与 Microsoft Dynamic LINQ 库结合使用时出现问题(在 这个 Scott Guthrie 的帖子) 像这样:

var results = mSession.Query();字符串 pId = "1";结果 = results.Where("Id.ToString().Contains(@0)", pId);

这会导致 NotSupportedException 带有System.String ToString()"消息(这与我在实现之前通过静态查询获得的消息完全相同)上面提到的类).使用NHibernate"的来源和at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitMethodCallExpression(MethodCallExpression expression)"处的StackTrace引发此异常.>

那么我在这里错过了什么?我做错了什么,或者需要做些什么来支持这种情况?

解决方案

我遇到了同样的问题并修复了它.
首先,我要感谢 murki 提供的信息,让我走上正轨!

部分答案在 Fabio 的帖子中.要解决此问题,您必须在 CustomLinqToHqlGeneratorsRegistry 构造函数中使用 RegisterGenerator 而不是 Merge 方法.我对 CustomLinqToHqlGeneratorsRegistry 类的实现如下:

公共类 CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry{公共 CustomLinqToHqlGeneratorsRegistry(): 根据(){MethodInfo toStringMethod = ReflectionHelper.GetMethodDefinition(x => x.ToString());RegisterGenerator(toStringMethod, new ToStringGenerator());}}

I'm using NHibernate 3.1.0 and I'm trying to extend the LINQ provider by using BaseHqlGeneratorForMethod and extending the DefaultLinqToHqlGeneratorsRegistry as explained in Fabio's post.

For example, to support ToString() I've created a ToStringGenerator as below.

internal class ToStringGenerator : BaseHqlGeneratorForMethod
{
    public ToStringGenerator()
    {
        SupportedMethods = new[]
            {
                ReflectionHelper.GetMethodDefinition<object>(x => x.ToString())
            };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        return treeBuilder.Cast(visitor.Visit(targetObject).AsExpression(), typeof(string));
    }
}

and I have registered using

internal class CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public CustomLinqToHqlGeneratorsRegistry()
    {
        this.Merge(new ToStringGenerator());
    }
}

etc. So far this works for "static" queries, I can use it like this:

var results = mSession.Query<Project>();
string pId = "1";
results = results.Where(p => p.Id.ToString().Contains(pId));

This translates correctly to its SQL counterpart (using SQL Server 2008)

where cast(project0_.Id as NVARCHAR(255)) like (''%''+@p0+''%'')

The problem arises when I try to use it in combination with Microsoft Dynamic LINQ library (discussed in this Scott Guthrie's post) like this:

var results = mSession.Query<Project>();
string pId = "1";
results = results.Where("Id.ToString().Contains(@0)", pId);

This results in a NotSupportedException with a message of "System.String ToString()" (which was the exact same messages I was getting with the static queries before implementing the classes mentioned above). This exception is being thrown with a source of "NHibernate" and with the StackTrace at "at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitMethodCallExpression(MethodCallExpression expression)".

So what am I missing here? What have I done wrong, or what needs to be done to support this scenario?

解决方案

I had the same problem and fixed it.
At first I want to thank murki for providing the information which got me on my way!

The answer lies partly in Fabio's post. To solve this issue you have to use the RegisterGenerator instead of the Merge method in the CustomLinqToHqlGeneratorsRegistry constructor. My implementation of the CustomLinqToHqlGeneratorsRegistry class is as follows:

public class CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public CustomLinqToHqlGeneratorsRegistry()
        : base()
    {
        MethodInfo toStringMethod = ReflectionHelper.GetMethodDefinition<int>(x => x.ToString());
        RegisterGenerator(toStringMethod, new ToStringGenerator());
    }
}

这篇关于将 LINQ 扩展到 Nhibernate 提供程序,结合动态 LINQ 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆