You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When query filter is defined through FluentMappingBuilder using the Func<IQueryable<T>, IDataContext, IQueryable<T>> type definition and it contains any joins, "Stack overflow" error occurs.
Provided example is using SQLite, I have also confirmed this behavior using .NET 6 and MSSQL server.
EDIT: When query cache is disabled, everything works as expected.
For background: Usage of query filters is necessary, as we need certain conditions to apply always, including when we are traversing through entity associations in our queries. (Either directly or by AutoMapper's expression-based projections)
(NB! We have also developed our own multi-filter-to-single-filter aggregator as Linq2Db is currently not supporting multiple simultaneous query filters. I should maybe create a feature-request on this?)
Exception message: Stack overflow.
Stack trace:
at System.RuntimeMethodHandle.GetMethodInstantiationPublic(System.IRuntimeMethodInfo)
at System.Reflection.RuntimeMethodInfo.get_ContainsGenericParameters()
at System.Linq.Expressions.Expression.ValidateMethodInfo(System.Reflection.MethodInfo, System.String)
at System.Linq.Expressions.Expression.ValidateMethodAndGetParameters(System.Linq.Expressions.Expression, System.Reflection.MethodInfo)
at System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression, System.Reflection.MethodInfo, System.Linq.Expressions.Expression)
at System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression, System.Reflection.MethodInfo, System.Collections.Generic.IEnumerable`1<System.Linq.Expressions.Expression>)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TransformX(System.Linq.Expressions.MethodCallExpression)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Transform(System.Linq.Expressions.Expression)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Transform[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IList`1<System.__Canon>)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TransformX(System.Linq.Expressions.MethodCallExpression)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Transform(System.Linq.Expressions.Expression)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Transform[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IList`1<System.__Canon>)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TransformX(System.Linq.Expressions.MethodCallExpression)
at LinqToDB.Expressions.TransformVisitor`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Transform(System.Linq.Expressions.Expression)
at LinqToDB.Expressions.ExpressionExtensions.Transform[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Linq.Expressions.Expression, System.__Canon, System.Func`3<System.__Canon,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression>)
at LinqToDB.Linq.Builder.ExpressionBuilder.CorrectDataConnectionReference(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression)
at LinqToDB.Linq.Builder.TableBuilder+<>c.<ApplyQueryFilters>b__7_0(System.ValueTuple`2<System.Delegate,System.Linq.IQueryable>, System.Reflection.MemberInfo, LinqToDB.IDataContext)
at LinqToDB.Linq.QueryableMemberAccessor`1[[System.ValueTuple`2[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Execute(System.Reflection.MemberInfo, LinqToDB.IDataContext)
at LinqToDB.Expressions.EqualsToVisitor.CompareMemberExpression(System.Reflection.MemberInfo, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsToX(System.Linq.Expressions.MethodCallExpression, System.Linq.Expressions.MethodCallExpression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.DefaultCompareArguments(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsToX(System.Linq.Expressions.MethodCallExpression, System.Linq.Expressions.MethodCallExpression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.DefaultCompareArguments(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsToX(System.Linq.Expressions.MethodCallExpression, System.Linq.Expressions.MethodCallExpression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
... (identical rows for hundreds of times) ...
at LinqToDB.Expressions.EqualsToVisitor.DefaultCompareArguments(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsToX(System.Linq.Expressions.MethodCallExpression, System.Linq.Expressions.MethodCallExpression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.CompareMemberExpression(System.Reflection.MemberInfo, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsToX(System.Linq.Expressions.MethodCallExpression, System.Linq.Expressions.MethodCallExpression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.DefaultCompareArguments(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsToX(System.Linq.Expressions.MethodCallExpression, System.Linq.Expressions.MethodCallExpression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, EqualsToInfo)
at LinqToDB.Expressions.EqualsToVisitor.EqualsTo(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression, LinqToDB.IDataContext, System.Collections.Generic.IReadOnlyDictionary`2<System.Linq.Expressions.Expression,LinqToDB.Linq.QueryableAccessor>, System.Collections.Generic.IReadOnlyDictionary`2<System.Reflection.MemberInfo,LinqToDB.Linq.QueryableMemberAccessor>, System.Collections.Generic.IReadOnlyDictionary`2<System.Linq.Expressions.Expression,System.Linq.Expressions.Expression>, Boolean)
at LinqToDB.Linq.Query.Compare(LinqToDB.IDataContext, System.Linq.Expressions.Expression)
at LinqToDB.Linq.Query`1+QueryCache+QueryCacheEntry[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Compare(LinqToDB.IDataContext, System.Linq.Expressions.Expression, LinqToDB.Linq.QueryFlags)
at LinqToDB.Linq.Query`1+QueryCache[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Find(LinqToDB.IDataContext, System.Linq.Expressions.Expression, LinqToDB.Linq.QueryFlags, LinqToDB.DataOptions)
at LinqToDB.Linq.Query`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetQuery(LinqToDB.IDataContext, System.Linq.Expressions.Expression ByRef, Boolean ByRef)
at LinqToDB.Linq.ExpressionQuery`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetQuery(System.Linq.Expressions.Expression ByRef, Boolean, Boolean ByRef)
at LinqToDB.Linq.ExpressionQuery`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].get_SqlText()
at LinqToDB.Linq.ExpressionQueryImpl`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToString()
at Program.<Main>$(System.String[])
Steps to reproduce
Create new console application. Install nugets linq2db (5.4.1) and System.Data.SQLite.Core (1.0.118) and then paste this code into Program.cs:
using LinqToDB;using LinqToDB.Data;using LinqToDB.Mapping;usingvardbCtx=new MyDbCtx(new DataOptions(new ConnectionOptions(){ConnectionString="Data Source=:memory:;Version=3;New=True;",ProviderName= ProviderName.SQLite
}));
dbCtx.CreateTable<User>();
dbCtx.CreateTable<Post>();varquery= dbCtx.GetTable<Post>().Where(x => x.Content.StartsWith("A"));varresult= query.ToList();
Console.ReadLine();// Add break-point here and try to look at query.SqlTextpublicclassMyDbCtx:DataConnection{publicMyDbCtx(DataOptionsoptions):base(options){varbuilder=new FluentMappingBuilder(MappingSchema.Default);
builder.Entity<Post>().HasQueryFilter((q,ctx)=> q.InnerJoin( ctx.GetTable<User>(),(p,u)=> p.UserId == u.Id && u.Name.StartsWith("B"),(p,u)=> p).Distinct());
builder.Build();
AddMappingSchema(builder.MappingSchema);}}publicrecordUser{publicGuidId{get;set;}publicstringName{get;set;}=null!;}publicrecordPost{publicGuidId{get;set;}publicGuidUserId{get;set;}publicstringContent{get;set;}=null!;}
The text was updated successfully, but these errors were encountered:
joonatanu-softwerk
changed the title
Global Filters with Joins cause stack overflow
Global Filters with Joins cause stack overflow when query cache is enabled
May 16, 2024
Describe your issue
When query filter is defined through
FluentMappingBuilder
using theFunc<IQueryable<T>, IDataContext, IQueryable<T>>
type definition and it contains any joins, "Stack overflow" error occurs.Provided example is using SQLite, I have also confirmed this behavior using .NET 6 and MSSQL server.
EDIT: When query cache is disabled, everything works as expected.
For background: Usage of query filters is necessary, as we need certain conditions to apply always, including when we are traversing through entity associations in our queries. (Either directly or by AutoMapper's expression-based projections)
(NB! We have also developed our own multi-filter-to-single-filter aggregator as Linq2Db is currently not supporting multiple simultaneous query filters. I should maybe create a feature-request on this?)
Steps to reproduce
Create new console application. Install nugets
linq2db (5.4.1)
andSystem.Data.SQLite.Core (1.0.118)
and then paste this code intoProgram.cs
:Environment details
Linq To DB
version: 5.4.1Database (with version): SQLite 1.0.118
ADO.NET Provider (with version): System.Data.SQLite.Core 1.0.118
Operating system: Windows 11
.NET Version: 8.0
The text was updated successfully, but these errors were encountered: