ExpressionVisitor.Visit在Data Service Query Visitor中抛出'必须是可简化的节点'错误

时间:2013-05-01 19:29:49

标签: c# wcf-data-services linq-expressions expressionvisitor

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

IRepository<IOrder> : IQueryable<T>

总的来说,这个概念在数据服务介入之前一直运行良好。我目前正在使用NuGet的Data Services v5.4。如果我在我的存储库上执行像ToList()这样简单的操作,一切正常,翻译将结果转换为OData服务的Orders列表。但是,如果我尝试执行orderby,则查询表达式变得更加复杂,并且在尝试创建可查询类型的接口变体的实例时无法填充返回类型。即尝试创建IOrder而不是Order。

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

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

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

显然,这是违反断开连接类型的口头禅,因为我的客户端应用程序必须知道数据服务库中的强类型“订单”,我想避免以防万一我想要切换出OData将来

接下来,我偶然发现了数据服务客户端的Context类,它允许您处理解析类型的方法,但在我的情况下,解决方案由于某种原因从未被调用过。

我后来开始关注的是ExpressionVisitors,我仍然认为这是我的故障,它必须能够将任何IOrder参数转换为我的存储库中的Order参数,以便查询返回强类型但继续接口类型的外观。

使用空壳ExpressionVisitor实现时,例如

MyVisitor : ExpressionVisitor

这适用于非数据服务查询(例如像List一样可查询),但对于数据服务存储库模式查询,您会收到无用的(至少对我而言)消息“必须是可简化的节点”。我猜测的是,表达式树访问者已经点击了一个对数据服务查询自定义的节点类型,并且不知道如何处理它。但是我认为ExpressionVisitor会简单地复制树中的内容,除非被告知做一些不同的事情?

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

1 个答案:

答案 0 :(得分:0)

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

https://github.com/object/MongOData

在将查询转换为MongoDB LINQ表达式以及将结果转换为DSPResource时,它处理表达式访问者。

NB!你想要实现的目标并不容易。但希望这个例子有所帮助。