簡體   English   中英

在IEnumerable上使用&#39;Any&#39; <string> 在OData LINQ查詢中

[英]Using 'Any' on IEnumerable<string> in OData LINQ query

我使用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”)

您可以按照我的博客http://coding.grax.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個請求。

我不知道在Linq到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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM