Here is an example of EF Core 8 translating LINQ to embedded collections:
And it works just fine:
public class Person
{
public string Name { get; set; } = null!;
public string Address { get; set; } = null!;
}
DbSet<Person> db;
var searchTerms = new[] { "Search #1", "Search #2", "Search #3"};
var linqQuery = db.Where(a => searchTerms.Contains(a.Address)).ToQueryString();
// DECLARE @__searchTerms_0 nvarchar(4000) = N'["Search #1","Search #2","Search #3"]';
// SELECT
// [a].[Name], [a].[Address]
// FROM
// [PERSON] AS[a]
// WHERE
// [a].[Address] IN(
// SELECT [s].[value]
// FROM OPENJSON(@__searchTerms_0) WITH([value] varchar(8000) '$') AS[s]
// )
But I can't achieve the same result using an expression.
Here is what I try and expect to get OPENJSON
:
DbSet<Person> db;
var searchTerms = new[] { "Search #1", "Search #2", "Search #3"};
var propInfo = typeof(Person).GetProperty(nameof(Person.Address))!;
var parameterExp = Expression.Parameter(typeof(Person), "a");
var method = typeof(Enumerable)
.GetMethods()
.First(n => n.Name == "Contains" && n.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(string));
var containsExp = Expression.Call(
genericMethod,
Expression.Constant(searchTerms, typeof(IEnumerable<string>)),
Expression.Property(parameterExp, propInfo));
var predicate = Expression.Lambda<Func<Person, bool>>(containsExp, parameterExp);
var expressionQuery = db.Where(predicate).ToQueryString();
// SELECT
// SELECT[a].[Name], [a].[Address]
// FROM
// [PERSON] AS[a]
// WHERE
// [a].[Address] IN(
// 'Search #1',
// 'Search #2',
// 'Search #3'
// )
Enumerable<string>.Contains
is already translated into "in (...)" have you tried with a complex type?a => searchTerms.Contains(a.Address)
already is an expression. You get a different query because the expression you tried to create operator-by-operator doesn't match the initial one. Why are you doing this in the first place though? Thatwhy
matters. LINQ is already generic and dynamically composable. You can writeif (addressTerms.Length>-) { query=query.Where(a => searchTerms.Contains(a.Address));}
. Are you trying to apply dynamic UI filters to your query? In that case you probably need to useLinqKit
.