Несколько значений с динамическим Linq

Как использовать множественное значение с контейнером в Dynamic Linq.

Ожидается при обычном Linq:

using System;
using System.Linq;
public class Simple {
  public static void Main() {
    string[] names = { "Burke", "Laptop", "Computer", 
                       "Mobile", "Ahemed", "Sania", 
                       "Kungada", "David","United","Sinshia" };
      string[] vars = {"i","a"};
      var query = names.Where(i=> vars.Any(j=>i.Contains(j))).ToList();

      Console.WriteLine(query.Count);
  }
}

Ожидаемый SQL

SELECT * FROM User WHERE (NAME LIKE '%a%'OR NAME LIKE '%b%')

Пробовал Dynamic Linq:

query = query.Where("new[]{\"a\",\"c\"}.Any(i=>i.Contains(it.ProductName))");

Исключение возврата:

No property or field 'ProductName' exists in type 'String'

Зависит от:


person OMANSAK    schedule 23.08.2019    source источник
comment
это работает? i=> i.Contains(vars.Any()))?   -  person vivek nuna    schedule 23.08.2019


Ответы (1)


Есть две проблемы с вашим "проверенным динамическим запросом":

  1. При переводе в динамический запрос вы смешали имена переменных, потому что i и j слишком похожи.

  2. it неоднозначен, поскольку есть 2 лямбда-выражения, и поэтому он анализируется как параметр самой внутренней лямбды.

Давайте сначала переименуем i в p (для "названий продуктов") и j в s (для "поиска"):

var query = names.Where(p => vars.Any(s => p.Contains(s))).ToList();

Затем вы можете напрямую преобразовать это в динамическое выражение Linq:

// The type of vars needs to be IEnumerable<string> otherwise Dynamic Linq does not see .Any
IEnumerable<string> vars = new[] {"i", "a"};
var query2 = names.Where("p => @0.Any(s => p.Contains(s))", vars).ToList();

Затем вы можете заменить аргумент внутренней лямбды на it

var query3 = names.Where("p => @0.Any(p.Contains(it))", vars).ToList();

Как видите, вы перепутали объект и аргумент Contains.

Затем вы можете применить выражение к EF-запросу. Таким образом, использование аргумента p становится p.ProductName:

IEnumerable<string> vars = new[] {"i", "a"};
query = query.Where("p => @0.Any(p.ProductName.Contains(it))", vars).ToList();

Или вот так:

IEnumerable<string> vars = new[] {"i", "a"};
query = query.Where("p => @0.Any(s => p.ProductName.Contains(s))", vars).ToList();
person hazzik    schedule 23.08.2019