question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Performing joins on the query containing nested query with FirstOrDefault fails

See original GitHub issue

Hi,

performing joins on the query containing nested query with FirstOrDefault fails.

Exception message:
Object reference not set to an instance of an object.

Stack trace:
   at LinqToDB.Linq.Builder.SelectContext.<>c.<ConvertToIndexInternal>b__49_2(ValueTuple`4 context, Int32 n, IBuildContext ctx, Expression ex, Int32 l, Expression _)
   at LinqToDB.Linq.Builder.SelectContext.ProcessMemberAccess[T,TContext](TContext context, Expression expression, MemberExpression levelExpression, Int32 level, Func`7 action)
   at LinqToDB.Linq.Builder.SelectContext.ConvertToIndexInternal(Expression expression, Int32 level, ConvertFlags flags)
   at LinqToDB.Linq.Builder.SelectContext.ConvertToIndex(Expression expression, Int32 level, ConvertFlags flags)
   at LinqToDB.Linq.Builder.SubQueryContext.ConvertToSql(Expression expression, Int32 level, ConvertFlags flags)
   at LinqToDB.Linq.Builder.ExpressionContext.ConvertToSql(Expression expression, Int32 level, ConvertFlags flags)
   at LinqToDB.Linq.Builder.ExpressionBuilder.ConvertToSql(IBuildContext context, Expression expression, Boolean unwrap, ColumnDescriptor columnDescriptor, Boolean isPureExpression)
   at LinqToDB.Linq.Builder.JoinBuilder.BuildJoin(ExpressionBuilder builder, SqlSearchCondition condition, IBuildContext outerKeyContext, Expression outerKeySelector, IBuildContext innerKeyContext, Expression innerKeySelector)
   at LinqToDB.Linq.Builder.JoinBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.FirstSingleBuilder.BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.MethodCallBuilder.BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.BuildSequence(BuildInfo buildInfo)
   at LinqToDB.Linq.Builder.ExpressionBuilder.Build[T]()
   at LinqToDB.Linq.Query`1.CreateQuery(ExpressionTreeOptimizationContext optimizationContext, ParametersContext parametersContext, IDataContext dataContext, Expression expr)
   at LinqToDB.Linq.Query`1.GetQuery(IDataContext dataContext, Expression& expr, Boolean& dependsOnParameters)
   at LinqToDB.Linq.ExpressionQuery`1.GetQuery(Expression& expression, Boolean cache, Boolean& dependsOnParameters)
   at LinqToDB.Linq.ExpressionQuery`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at Linq2dbTest.Program.Main(String[] args) in Program.cs:line 34

Steps to reproduce

using LinqToDB;
using LinqToDB.Mapping;
using System.Linq;

namespace Linq2dbTest
{
    public static class Program
    {
        public static void Main()
        {
            var builder = MappingSchema.Default.GetFluentMappingBuilder();

            builder.Entity<Entity1>();

            builder.Entity<Entity2>();

            builder.Entity<Entity3>();

            using (var con = new Db())
            {
                var subquery = con.GetTable<Entity2>();

                var query = con.GetTable<Entity1>()
                    .Select(entity1 => new
                    {
                        Entity1 = entity1,
                        Entity2 = subquery.FirstOrDefault(entity2 => entity2.Id == entity1.Id)
                    })
                    .GroupJoin(con.GetTable<Entity3>(),
                        x => x.Entity2.Id,
                        x => x.Id,
                        (x, y) => x);

                var result = query.FirstOrDefault();
            }
        }

        public class Db : LinqToDB.Data.DataConnection
        {
            public Db() : base(ProviderName.SqlServer2017,
                "data source=localhost;initial catalog=xxx;integrated security=True;MultipleActiveResultSets=True")
            {
            }
        }

        public class Entity1
        {
            public int Id { get; set; }
        }

        public class Entity2
        {
            public int Id { get; set; }
        }

        public class Entity3
        {
            public int Id { get; set; }
        }
    }
}

Environment details

linq2db version: 3.5.1 Database Server: SQL Server 2019 Database Provider: SQL Operating system: W10 .NET Framework: 4.8

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
sdanylivcommented, Nov 18, 2021

Sorry for delay, try this one. Query syntax is more preferable here:

var query = 
    from e1 in con.GetTable<Entity1>()
    from e2 in subquery.Where(e2 => e2.Id == e1.Id)
        .Take(1)
        .DefaultIfEmpty()
    from e3 in con.GetTable<Entity3>().Where(e3 => e3.Id == e2.Id)
    select e3;

I’m working on fixing FirstOrDefault in queries, not easy task.

1reaction
stomasoviccommented, Nov 17, 2021

Hi,

We succeeded using Where.Take.DefaultIfEmpty instead of FirstOrDefault var query = con.GetTable<Entity1>() .Select(entity1 => new { Entity1 = entity1, Entity2 = subquery.FirstOrDefault(entity2 => entity2.Id == entity1.Id) }) use following instead: var query = con.GetTable<Entity1>() .Select(entity1 => new { Entity1 = entity1, Entity2 = subquery.Where(entity2 => entity2.Id == entity1.Id).Take(1).DefaultIfEmpty() })

Read more comments on GitHub >

github_iconTop Results From Across the Web

entity framework core - Using FirstOrDefault in a sub query
We are having major performance issues with some of our LINQ-to-SQL queries. We have a Case table, with a one-to-many relationship on ...
Read more >
Linq query causing performance Issue - Microsoft Q&A
Not sure FirstOrDefault is causing this. ... Maybe the problem is caused by multiple SQL queries that are performed inside the loop.
Read more >
Writing Better Performing Queries with LINQ on EF Core 6.0 ⚙️
In this case, doesn't matter if test passes for few or large numbers of entities, applying where first resulted in better performance. SELECT...
Read more >
Null or empty object when LINQ to Entities query returns ...
First() will yield null if the list is empty, but using .FirstOrDefault() would be simpler. What do you mean by "empty object", do...
Read more >
Remarks and limitations - LLBLGen Pro Runtime Framework v5. ...
Every 'let' statement wraps the inner query in a complete SELECT statement ... The problem isn't the check if both sequences contain the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found