我正在为我们的 odata v4 服务实现一些功能。我们希望支持所有函数的过滤查询选项,就像实体集合一样。
假设我们有一个 SearchProducts 函数,它接受一个 ProductType 参数,并返回属于特定 ProductType 的所有产品。
现在的问题是,我没有找到任何支持这种需求的 odata 内置方法。我能弄清楚的唯一方法是手动解析 FilterClause,然后将其应用于从函数返回的结果。
检查此示例代码:
IQueryable<Product> collection = _service.SearchProducts(ProductType.Phone);
var parser = new ODataUriParser(model, new Uri("SearchProducts(ProductType='Phone')?$filter=Name eq 'IPhone'", UriKind.Relative));
var filter = parser.ParseFilter();
// TODO: apply filter on collection, to filter all iphones. get the results same as the following code
// TODO: collection = collection.Where(p=>p.Name == "IPhone");
Run Code Online (Sandbox Code Playgroud)
该系列将是所有电话产品。添加 $filter 字符串后,它应该返回所有 iPhone 产品。
我可以将 FilterClause 解析为 lambda 表达式,然后将其应用于集合以返回正确的结果。但是考虑到 $filter 的复杂性,解析器可能会非常复杂并且会花费很多时间。
有人对此有快速解决方案吗?谢谢你
真正的问题是:如何在没有整个 odata 的 asp 基础结构的情况下使用 OData 查询语言进行过滤?\n可以通过提取 $filter 并将其应用到 IQuerable 数据库上下文来完成。\n搜索也可以完成同样的操作。这样我们就有了更大的灵活性,同时可以重用 OData sql 生成代码和解析逻辑。
\n首先,在 DI 中注册 this model,这样你就可以将它注入到任何地方:
ODataModelBuilder builder = new ODataConventionModelBuilder();\nbuilder.EntitySet<Order>("Orders");\nvar model = builder.GetEdmModel();\nRun Code Online (Sandbox Code Playgroud)\n\xc2\xa0\n然后,在您的控制器中接受过滤器参数作为字符串参数:
\nIActionResult Get(string filterParam) \n{\n // test query\n filterParam = "(MyCount ne 10) and (EnumField in ('1', '2')) and (Address/Id eq 1)";\nRun Code Online (Sandbox Code Playgroud)\n后来建立类似这样的东西。您可以在这里放置其他内容,例如 $search、$top、$count:
\nDictionary<string, string> options = new Dictionary<string, string>\n{\n\xc2\xa0 {"$filter", filterParam },\n};\nRun Code Online (Sandbox Code Playgroud)\n解析查询:
\nIEdmType type = model.FindDeclaredType("MyEntities.Order");\nIEdmNavigationSource source = model.FindDeclaredEntitySet("Orders");\nODataQueryOptionParser parser = new ODataQueryOptionParser(model, type, source, options);\nRun Code Online (Sandbox Code Playgroud)\n将其应用到您的数据库上下文集。IQuerable 将包含生成的 SQL,以缩小结果范围。
\nvar context = new ODataQueryContext(model, typeof(Order), null);\nvar opts = new ODataQueryOptions<Order>(context, this.Request);\nFilterQueryOption filterQuery = new FilterQueryOption(" ", context, parser);\n \nvar iQuerableResult = filterQuery.ApplyTo(_dbSet_dbContext, new ODataQuerySettings { });\nRun Code Online (Sandbox Code Playgroud)\n请记住,这是原始 PoC 代码。不是生产就绪的东西。
\n