Linq To Nhibernate:HqlTreeBuilder with Elements 如何使用
本文关键字:Elements 何使用 with HqlTreeBuilder To Nhibernate Linq | 更新日期: 2023-09-27 18:33:07
对于我正在开发的项目,我必须使用 Linq 来创建一些规范。现在我有一个字典,我必须在上面搜索值。由于 NHibernate 的默认 Linq 实现不支持 ContainsValue 函数,因此我决定创建自己的函数。
因此,我创建了一个名为ContainsValueGenerator的类,该类派生自BaseHqlForMethod,如下所示:
public class ContainsValueGenerator : BaseHqlGeneratorForMethod
{
public ContainsValueGenerator()
{
SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() => new Dictionary<object, object>().ContainsValue(null)) };
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
//Session.CreateQuery("from Message m where 'aDictionaryValue' in elements(m.Dictionary)");
HqlTreeNode hqlTreeNode = treeBuilder.Elements(); // TODO include dictionary here?
return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), hqlTreeNode);
//return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Indices(visitor.Visit(targetObject).AsExpression())); ContainsKey Method implementation
}
}
我查看了Nhibernate的源代码,并采用了ContainsKey方法实现。Hqlsyntax 与 ContainsKey 语法非常相似。唯一需要改变的是(我猜)而不是树构建器。索引(),我必须使用树构建器。元素(显示在注释中)。
这就是我陷入困境的地方;我无法为元素表达式提供我自己的字典。如何创建利用元素表达式的 HqlTreeNode?
提前感谢, 罗伯·范帕梅尔
解决方案是创建自己的 HqlElements 类,该类继承自 HqlExpression。事实上,它只是 HqlIndices 类的副本。
public class HqlElements : HqlExpression
{
public HqlElements(IASTFactory factory, HqlExpression dictionary)
: base(HqlSqlWalker.ELEMENTS, "elements", factory, dictionary)
{
}
}
棘手的部分是将其作为属性添加到 HqlTreeBuilder 类中。因此,您可以使用扩展方法。这包含一段丑陋的代码,用于获取带有反射的HqlTreeBuilder的工厂。
public static class HqlTreeBuilderExtensions
{
public static HqlElements Elements(this HqlTreeBuilder treeBuilder, HqlExpression dictionary)
{
var factory = (IASTFactory) treeBuilder.GetType().GetField("_factory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(treeBuilder);
return new HqlElements(factory, dictionary);
}
}
您的生成器现在可以更改为:
public class ContainsValueGenerator : BaseHqlGeneratorForMethod
{
public ContainsValueGenerator()
{
SupportedMethods = new[] { ReflectionHelper.GetMethodDefinition(() => new Dictionary<object, object>().ContainsValue(null)) };
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
return treeBuilder.In(visitor.Visit(arguments[0]).AsExpression(), treeBuilder.Elements(visitor.Visit(targetObject).AsExpression()));
}
}
最好的解决方案是这段代码将它变成NHibernate本身。也许我会为此在 GitHub 上添加一个补丁。