帮助 nHibernate linq 提供程序扩展的表达式
我正在通过扩展 BaseHqlGeneratorForMethod 为 nHibernate 开发自定义 linq 扩展。该技术记录如下: http://fabiomaulo.blogspot.com/2010/07/nhibernate -linq-provider-extension.html
我已经成功地为各种类型的操作实现了这些,但我必须说 - 将简单的 linq 表达式转换为它的完整表达树并不容易!我现在被困在一个了。
对于此示例,我有三个实体。 员工
、组
和员工组
。 EmployeeGroup 类在 Employee 和 Group 之间建立多对多关系。我必须专门创建中间类,因为还有其他属性可以跟踪每个员工在每个组中拥有的特定权限。所以有两个一对多的关系,而不是一个nHibernate的多对多关系。
现在假设我想要获取包含特定员工的所有组。我可以编写这个查询:
var groups = session.Query<Group>()
.Where(g => g.EmployeeGroups.Any(eg => eg.Employee == employee));
这工作正常,但需要输入很多内容。我更愿意能够做到这一点:
var groups = session.Query<Group>().Where(g => g.HasEmployee(employee));
我首先创建一个扩展方法,如下所示:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
这在查询本地组列表时有效,但不适用于 nHibernate 会话。为此,我还必须创建一个 linq 扩展并注册它。就像本文(上面链接)中一样,我创建了一个扩展 BaseHqlGeneratorForMethod
的 GroupHasEmployeeGenerator
类。我设置其 .SupportedMethods
属性来引用我的 HasEmployee 扩展方法。
我迷失的地方是对 BuildHql
的覆盖。要构建的表达式很快就会变得复杂。我认为,由于我要替换 .Any
子句 - 一个好的起点是内置 AnyHqlGenerator
类的源代码。但这没有考虑到源是原始元素的属性,也没有考虑到我没有 lambda 表达式来表示 where 子句。我需要手动构建这些部件。
到目前为止,发布我的尝试是没有意义的,因为它们离任何有效的方法都还很远。
有人可以帮我将这个简单的表达式转换为 BuildHql
方法覆盖的适当方法集吗?
如果有任何更好的文档,请告诉我。谢谢。
I'm working on a custom linq extension for nHibernate by extending the BaseHqlGeneratorForMethod. The technique is documented here:
http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html
I've had success with implementing these for various types of operations, but I must say - converting a simple linq expression to its full expression tree is not easy! I'm stuck on one now.
For this example, I have three entities. Employee
, Group
, and EmployeeGroup
. The EmployeeGroup class sets up a many-to-many relationship between Employee and Group. I must specifically create the intermediate class because there are additional properties to track like specific permissions each employee has in each group. So there are two one-to-many relationships, rather than an nHibernate many-to-many relationship.
Now say I want to get all groups that contain a specific employee. I can write this query:
var groups = session.Query<Group>()
.Where(g => g.EmployeeGroups.Any(eg => eg.Employee == employee));
This works fine, but it's a lot to type. I'd much rather be able to do this:
var groups = session.Query<Group>().Where(g => g.HasEmployee(employee));
I start by creating an extension method like so:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This works when querying a local list of groups, but not against the nHibernate session. For that, I have to also create a linq extension and register it. Just like in the article (linked above), I create a GroupHasEmployeeGenerator
class that extends BaseHqlGeneratorForMethod
. I set its .SupportedMethods
property to reference my HasEmployee extension method.
Where I get lost is in the override to BuildHql
. The expression to build gets complicated pretty fast. I figure since I'm replacing the .Any
clause - a good place to start is with the source for the built-in AnyHqlGenerator
class. But that doesn't take into account that the source is a property of the original element, and it also doesn't take into account that I don't have a lambda expression to represent the where clause. I need to build these parts manually.
There's no point in posting my attempts so far, as they've all be quite far from anything that would work.
Will someone please help me convert this simple expression into the approprate set of methods for the BuildHql
method override?
If there is any better documentation out there for this, please let me know. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我知道这个问题已经有一年了,但是我今天在实现 BaseHqlGeneratorForMethod 时遇到了一个非常类似的问题。
BuildHql
的输入包含传递给扩展方法的System.Linq.Expressions.Expression
参数的集合。使用这些参数,您可以构建表示扩展方法的实现的表达式树。如果 NHibernate.Linq 支持生成的表达式,那么您可以使用提供的 IHqlExpressionVisitor 将该表达式转换为 Hql 的子树。在您的示例中:
这将变得与此类似:
我无法真正测试这个特定示例,但在为我自己的扩展方法提供支持时,相同的方法对我有用。
I know this question is a year old, but I ran into a very similar issue when implementing
BaseHqlGeneratorForMethod
today.The input to
BuildHql
contains a collection ofSystem.Linq.Expressions.Expression
arguments that are passed to your extension method. Using these arguments, you can build an expression tree that represents the implementation of your extension method. If the resulting expression is something NHibernate.Linq supports, then you can transform that expression to a subtree of Hql using the providedIHqlExpressionVisitor
.In your example:
This would become something similar to this:
I can't really test this specific example, but the same approach worked for me when providing support for my own extension method.