Я могу получить объекты из EF с таким запросом:
apples = apples.Where(a => a.Sort.Name.StartsWith("Gold"))
но мне интересно, возможно ли использовать список строк вместо одной строки? Я уже пытался сделать это так:
List<string> list = {...}
apples = apples.Where(a => list.Any(x => a.Sort.Name.StartsWith(x)))
но это дает мне странную ошибку:
System.ArgumentOutOfRangeException: указанный аргумент находится вне диапазона допустимых значений. (Параметр «индекс») в System.Linq.Expressions.InstanceMethodCallExpression1.GetArgument (индекс Int32) в Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionVisitors.NpgsqlSqlTranslatingExpressionVisitor.VisitLikeAnyAll (выражение SubQueryExpression) в Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionVisitors.NpgsqlSqlTranslatingExpressionVisitor.VisitSubQuery (выражение SubQueryExpression) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit (выражение выражения) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitBinary (выражение BinaryExpression) в Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionVisitors.NpgsqlSqlTranslatingExpressionVisitor.VisitBinary (выражение BinaryExpression) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit (выражение выражения) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitBinary (выражение BinaryExpression) в Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionVisitors.NpgsqlSqlTranslatingExpressionVisitor.VisitBinary (выражение BinaryExpression) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit (выражение выражения) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitBinary (выражение BinaryExpression) в Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionVisitors.NpgsqlSqlTranslatingExpressionVisitor.VisitBinary (выражение BinaryExpression) в Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit (выражение выражения) в Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, индекс Int32) в Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection
1 bodyClauses, QueryModel queryModel) at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel) at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel(QueryModel queryModel) at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel(QueryModel queryModel) at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateAsyncQueryExecutor[TResult](QueryModel queryModel) at Microsoft.EntityFrameworkCore.Storage.Database.CompileAsyncQuery[TResult](QueryModel queryModel) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQueryCore[TResult](Expression query, IQueryModelGenerator queryModelGenerator, IDatabase database) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass22_0
1.b__0() в Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
1.System.Collections.Generic.IAsyncEnumerable.GetEnumerator() в System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](накопитель IAsyncEnumerable1 source, TAccumulate seed, Func
3, Func`2 resultSelector, CancellationToken CancellationToken) в D:\a\1\s\Ix.NET\Source\System.Interactive.Async \Aggregate.cs:строка 118 в {мой проект}
Сорт — это объект, есть таблица со всеми сортами, поэтому у каждого яблока есть сорт и у каждого сорта есть имя. Мне просто нужно выбрать только яблоки из базы данных, имена которых начинаются с любой строки из списка
Вам нужно указать, какой LINQ to EF вы используете: EF 6.x, EF Core 2.0/2.1/3.x/5.x?
Не смог получить ту же ошибку, что и вы (только что получил неудачный перевод, поэтому было бы здорово, если бы вы могли добавить минимальный воспроизводимый пример), у меня работало с использованием EF.Functions.ILike
(с последним пакетом npgsql):
List<string> list = new() {"a%", "b%"};
var result = ctx.Apples
.Where(c => list.Any(xx => EF.Functions.ILike(c.Sort.Name, xx)))
.ToList();
Насколько я вижу, поддержка использования StartsWith
с локальной коллекцией на данный момент не реализована (на основании этого PR и этого комментария), только EF.Functions.Like
и EF.Functions.ILike
.
Если вы хотите использовать LINQKit, вы можете создать методы расширения для построения выражений из локальных коллекций:
// searchTerms - IEnumerable<TSearch> where one must match for a row
// testFne(row,searchTerm) - test one of searchTerms against a row
// r => searchTerms.Any(s => testFne(r,s))
public static Expression<Func<T, bool>> AnyIs<T, TSearch>(this IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) {
var pred = PredicateBuilder.New<T>();
foreach (var s in searchTerms)
pred = pred.Or(r => testFne.Invoke(r, s));
return pred;
}
// searchTerms - IEnumerable<TSearch> where one must match for a row
// testFne(row,searchTerm) - test one of searchTerms against a row
// dbq.Where(r => searchTerms.Any(s => testFne(r,s)))
public static IQueryable<T> WhereAny<T,TSearch>(this IQueryable<T> dbq, IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) =>
dbq.AsExpandable().Where(searchTerms.AnyIs(testFne));
Затем вы можете использовать их с вашим запросом:
List<string> list = {...}
apples = apples.WhereAny(list, (a,s) => a.Sort.Name.StartsWith(s));
Конечно, вы также можете создать свой собственный мини-LINQKit для выполнения той же задачи (хотя это не совсем так).
Что вы имеете в виду под a.Sort? Вы сортируете одно яблоко?