使用';任何';在IEnumerable<;字符串>;在OData LINQ查询中
本文关键字:LINQ OData gt 查询 IEnumerable 任何 使用 lt 字符串 | 更新日期: 2023-09-27 18:29:25
我正在使用Microsoft.Data.Odata
(5.6)运行以下查询:
IEnumerable<Service> services = context.Services.Expand(ServiceQueryExpansion)
.Where(c =>
(serviceNames.Any(s => s.Equals(
c.ServiceName, StringComparison.OrdinalIgnoreCase))))
serviceNames是字符串的IEnumerable
我在尝试上述查询时遇到以下错误:
Error translating Linq expression to URI: The source parameter for the 'Any' method has to be either a navigation or a collection property.
如何解决此问题?
我知道这很有趣,也很令人兴奋(讽刺),但您可以动态构建这样的Where表达式:
var serviceNames = new string[] { "SERVICE1","SERVICE2"};
Expression<Func<Service,bool>> inList = v => false;
var parameter = inList.Parameters[0];
var propertyExpression = Expression.Property(parameter,"ServiceName");
foreach (var serviceName in serviceNames)
{
var body = inList.Body;
var constantExpression = Expression.Constant(serviceName);
var equalityExpression = Expression.Equal(propertyExpression,constantExpression);
body = Expression.OrElse(body,equalityExpression);
inList = Expression.Lambda<Func<Service, bool>>(body, parameter);
}
IEnumerable<Service> services = context.Services.Expand(ServiceQueryExpansion)
.Where(inList);
此方法从您的列表中构建一个自定义where子句,该子句类似于(v=>v.ServiceName=="Service1"||v.ServiceName==="Service2"|| v.ServiceName=]"Service3")
你可能会按照我博客上的指示https://secureapplicationlifestyle.com/2013/07/filter-pattern-for-linq-query-filter.html将此逻辑封装到自定义的"WhereContains(yourListHere)"自定义筛选器扩展方法中。
您可以编写:
var services = context.Services.Expand(ServiceQueryExpansion).AsEnumerable()
.Where(c => serviceNames.Contains(c.ServiceName));
但它将下载整个服务集合。或者:
var services = serviceNames.SelectMany(s=>
context.Services.Expand(ServiceQueryExpansion).Where(c=> c.ServicaName == s));
这将创建N个请求。
我不知道有什么更好的方法可以在林克对OData做到这一点。
我所做的是应用我可以应用的过滤器,然后列出,然后在本地获得结果后再制作另一个过滤器。
var services = context.Services.Expand(ServiceQueryExpansion).ToList();
services = services.Where(s => serviceNames.Any(n => n.ServiceName.Equals(s, StringComparison.OrdinalIgnoreCase)));
如果你有几个不需要通过网络获取的记录,这不是最好的选择。
另一个选项是创建数据服务操作。
[WebGet]
public IQueryable<Service> GetServicesByServiceName(string serviceNames)
{
var serviceNamesArray = serviceNames.Split(',');
var ctx = YourContext();
return ctx.Services.Include("ServiceQueryExpansion").Where(s => serviceNamesArrays.Any(n => s.ServiceName.Equals(n, StringComparison.OrdinalIgnoreCase))).AsQueryable();
}