System.Linq.Dynamic.Core
System.Linq.Dynamic.Core copied to clipboard
SelectMany collectionSelectorArgs not allowing context.Set<>()
1. Description
If an additional DBSet is used via SelectMany, this cannot be resolved.
2. Exception
Exception message:
Unhandled exception. No property or field 'Set' exists in type 'SampleContext' (at index 8)
Stack trace:
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMemberAccess(Type type, Expression expression) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 1891
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 819
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseUnary() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 806
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseArithmetic() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 751
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAdditive() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 718
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseShiftOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 694
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 482
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 414
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 325
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 308
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 290
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 270
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 257
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 241
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAsLambda(String id) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 1963
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMemberAccess(Type type, Expression expression) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 1882
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIdentifier() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 1058
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimaryStart() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 843
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 811
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseUnary() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 806
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseArithmetic() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 751
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAdditive() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 718
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseShiftOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 694
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 482
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 414
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 325
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 308
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 290
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 270
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 257
at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator() in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 241
at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse(Type resultType, Boolean createParameterCtor) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\Parser\ExpressionParser.cs:line 156
at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(Type delegateType, ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 121
at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, ParameterExpression[] parameters, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 98
at System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParsingConfig parsingConfig, Boolean createParameterCtor, Type itType, Type resultType, String expression, Object[] values) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicExpressionParser.cs:line 357
at System.Linq.Dynamic.Core.DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, String collectionSelector, String resultSelector, String collectionParameterName, String resultParameterName, Object[] collectionSelectorArgs, Object[] resultSelectorArgs) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs:line 2085
at System.Linq.Dynamic.Core.DynamicQueryableExtensions.SelectMany(IQueryable source, String collectionSelector, String resultSelector, String collectionParameterName, String resultParameterName, Object[] collectionSelectorArgs, Object[] resultSelectorArgs) in C:\Dev\GitHub\System.Linq.Dynamic.Core\src\System.Linq.Dynamic.Core\DynamicQueryableExtensions.cs:line 2114
at Program.Main()
3. Fiddle or Project
Sample includes a static version which is working and the dynamic which will fail.
https://dotnetfiddle.net/NwtrN5
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class Program
{
public static void Main()
{
var context = new SampleContext();
context.Add(new TableOne { Id = 1 });
context.Add(new TableTwo { Id = 1, TableOneId = 2 });
context.SaveChanges();
var staticQuery = context.Set<TableOne>().SelectMany(t => context.Set<TableTwo>().Where(t2 => t2.TableOneId != t.Id),
(t, t2) => new { t, t2 });
Console.WriteLine(staticQuery.Expression.ToString());
var staticResult = staticQuery.ToList();
Console.WriteLine("static result: " + staticResult.Count.ToString());
var dynamicQuery = context.Set<TableOne>().SelectMany("t => @0.Set<TableTwo>().Where(t2 => t2.TableOneId != t.Id)",
"new (t as t, t2 as t2)", "t", "t2",
new object[] { context });
Console.WriteLine(dynamicQuery.Expression.ToString());
var dynamicResult = dynamicQuery.ToDynamicList();
Console.WriteLine("dynamic result: " + dynamicResult.Count.ToString());
}
public class SampleContext : DbContext
{
public SampleContext()
:base(GetOptions()) { }
private static DbContextOptions GetOptions()
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseInMemoryDatabase(Guid.NewGuid().ToString());
return optionsBuilder.Options;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<TableOne>().HasKey(x => x.Id);
modelBuilder.Entity<TableTwo>().HasKey(x => x.Id);
}
}
public record TableOne
{
public int Id { get; set; }
}
public record TableTwo
{
public int Id { get; set; }
public int TableOneId { get; set; }
}
}
4. Any further technical details
I know that we can combine 2 entities using Join or GroupJoin. However, the point is that different operators are supported and not just "=".
The static expression is supporting a method call to resolve the inner collection:
[Microsoft.EntityFrameworkCore.Query.EntityQueryRootExpression].SelectMany(t => value(Program+<>c__DisplayClass0_0).context.Set().Where(t2 => (t2.TableOneId != t.Id)), (t, t2) => new <>f__AnonymousType0`2(t = t, t2 = t2))