ExpressionVisitor.访问抛出'必须是可约节点'在数据服务查询访问器中出现错误

本文关键字:访问 查询 服务 数据 错误 ExpressionVisitor 节点 | 更新日期: 2023-09-27 18:11:38

我在WCF数据服务的存储库模式实现方面遇到了一个问题。总而言之,我正在尝试在客户机应用程序中使用存储库模式,该模式为所需的存储库使用可插拔模型。根本问题是我的存储库接口IRepository只能知道它所存储的项目的接口类型变体。这是为了将客户端应用程序从订单的数据服务实现中抽象出来,例如

IRepository<IOrder> : IQueryable<T>

一般来说,在涉及到Data Services之前,这个概念工作得很好。我目前使用的数据服务v5.4从NuGet。如果我在存储库上执行像ToList()一样简单的操作,那么一切都会正常工作,并且转换将结果转换为来自OData服务的订单列表。但是,如果我尝试执行订单,查询表达式就会变得更加复杂,并且无法填充返回类型,因为它试图创建可查询类型的接口变体的实例。例如,尝试创建IOrder的实例,而不是Order。

repository.OrderBy(order => order.Id).ToList(); // Fails

在客户端级别,但是如果我使用Cast强制类型,则它可以工作…

repository.Cast<Order>(order => order.Id).ToList(); // Suceeds

显然,这违背了断开连接类型的原则,因为我的客户端应用程序必须意识到来自数据服务库的强类型"Order",这是我想避免的,以防将来我想切换出OData。

接下来,我偶然发现了数据服务客户端上下文类,它允许您获取用于解析类型的方法的句柄,但是在我的情况下,由于某些原因,解析从未被调用过。

我随后开始关注的是ExpressionVisitors,我仍然相信它是我摆脱混乱的门票,它必须能够在我的存储库中将任何IOrder参数转换为Order参数,以便查询返回强类型,但继续接口类型的外观。

当使用空shell ExpressionVisitor实现时,例如

MyVisitor : ExpressionVisitor

这对于非数据服务查询(例如,像一个列表作为可查询的)工作得很好,但是对于数据服务存储库模式查询,您会收到无用的(至少对我来说)消息"必须是可简化的节点"。我猜测的是,表达式树访问者遇到了数据服务查询自定义的节点类型,并且不知道该如何处理它。然而,我认为一个ExpressionVisitor会简单地复制树中有什么,除非被告知做一些不同的事情?

无论如何,我要问的是,我如何通过使用这个ExpressionVisitor与OData查询来替换我的查询的返回类型?我试图寻找某种现有的数据服务表达访问者,但无法找到一个。我希望我的客户端数据服务从接口类型查询生成查询,但返回相同名称的强类型。

ExpressionVisitor.访问抛出'必须是可约节点'在数据服务查询访问器中出现错误

看看MongOData,这是一个使用WCF数据服务自定义提供程序构建的MongoDB OData提供程序:

https://github.com/object/MongOData

它处理表达式访问者,当转换查询到MongoDB LINQ表达式和转换结果到DSPResource时。

注!你想要达到的目标并不容易。但是希望这个例子能帮到你。