我正在使用NHibernate 3.1.0,我正在尝试使用BaseHqlGeneratorForMethod
扩展LINQ提供程序,并按照Fabio's post中的说明扩展DefaultLinqToHqlGeneratorsRegistry
。
例如,为了支持ToString()
,我创建了ToStringGenerator
,如下所示。
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));
}
}
我已使用
注册internal class CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public CustomLinqToHqlGeneratorsRegistry()
{
this.Merge(new ToStringGenerator());
}
}
等。到目前为止,这适用于“静态”查询,我可以这样使用它:
var results = mSession.Query<Project>();
string pId = "1";
results = results.Where(p => p.Id.ToString().Contains(pId));
这正确转换为SQL对应方(使用SQL Server 2008)
where cast(project0_.Id as NVARCHAR(255)) like (''%''+@p0+''%'')
当我尝试将它与Microsoft Dynamic LINQ库(在this Scott Guthrie's post中讨论)结合使用时出现问题:
var results = mSession.Query<Project>();
string pId = "1";
results = results.Where("Id.ToString().Contains(@0)", pId);
这会导致 NotSupportedException ,并显示消息“ System.String ToString()”(这与我在实施之前使用静态查询获得的完全相同的消息上面提到的类)。使用“ NHibernate ”源代码抛出此异常,并在“ at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitMethodCallExpression(MethodCallExpression expression)”中使用StackTrace。
那我在这里错过了什么?我做错了什么,或者需要做些什么来支持这种情况?
答案 0 :(得分:3)
我有同样的问题并修好了。
首先,我要感谢murki提供的信息让我顺利上路!
答案部分在于法比奥的帖子。要解决此问题,您必须在RegisterGenerator
构造函数中使用Merge
而不是CustomLinqToHqlGeneratorsRegistry
方法。我对CustomLinqToHqlGeneratorsRegistry
类的实现如下:
public class CustomLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public CustomLinqToHqlGeneratorsRegistry()
: base()
{
MethodInfo toStringMethod = ReflectionHelper.GetMethodDefinition<int>(x => x.ToString());
RegisterGenerator(toStringMethod, new ToStringGenerator());
}
}
答案 1 :(得分:1)
这里有两个明确定义的独立阶段:
由于您已确定静态表达式运行良好,因此问题出在 1。
如果您执行以下操作会发生什么?
var results = Enumerable.Empty<Project>().AsQueryable();
string pId = "1";
results = results.Where("Id.ToString().Contains(@0)", pId);
如果失败,你将确认这是单独使用Dynamic Linq的问题(即它不支持你正在喂它的表达式),所以你必须深入研究它并修补它。
半相关:ToStringGenerator
看起来很有用;你能为NHibernate提交一个补丁吗? http://jira.nhforge.org
答案 2 :(得分:0)
假设类Id
的属性Project
,Int32
尝试在Int32.ToString()
类中注册相应的ToStringGenerator
方法。
...
public ToStringGenerator()
{
SupportedMethods = new[]
{
ReflectionHelper.GetMethodDefinition<object>(x => x.ToString()),
ReflectionHelper.GetMethodDefinition<int>(x => x.ToString()),
};
}
...