Efcore: Query: "Null TypeMapping in Sql Tree" when projecting a null value DTO

Created on 30 May 2019  路  4Comments  路  Source: dotnet/efcore

query:

ctx.Squads.Select(
                    s => new
                    {
                        s.Name,
                        Gear = s.Members.Where(g => g.HasSoulPatch).Select(g => (MyDTO)null).FirstOrDefault()
                    })

exception:

Null TypeMapping in Sql Tree



D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalSqlTranslatingExpressionVisitor.cs(72,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.SqlTypeMappingVerifyingExpressionVisitor.VisitExtension(Expression node)
   at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalSqlTranslatingExpressionVisitor.cs(56,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalProjectionBindingExpressionVisitor.cs(106,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalProjectionBindingExpressionVisitor.cs(41,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalQueryableMethodTranslatingExpressionVisitor.cs(601,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
D:\git\EntityFrameworkCore\src\EFCore\Query\Pipeline\QueryableMethodTranslatingExpressionVisitor.cs(331,0): at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
D:\git\EntityFrameworkCore\src\EFCore\Query\Pipeline\QueryableMethodTranslatingExpressionVisitor.cs(31,0): at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalSqlTranslatingExpressionVisitor.cs(167,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalSqlTranslatingExpressionVisitor.cs(45,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalProjectionBindingExpressionVisitor.cs(106,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalProjectionBindingExpressionVisitor.cs(183,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.VisitNew(NewExpression newExpression)
   at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalProjectionBindingExpressionVisitor.cs(118,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalProjectionBindingExpressionVisitor.cs(41,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
D:\git\EntityFrameworkCore\src\EFCore.Relational\Query\PipeLine\RelationalQueryableMethodTranslatingExpressionVisitor.cs(601,0): at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
D:\git\EntityFrameworkCore\src\EFCore\Query\Pipeline\QueryableMethodTranslatingExpressionVisitor.cs(331,0): at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
D:\git\EntityFrameworkCore\src\EFCore\Query\Pipeline\QueryCompilationContext2.cs(61,0): at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryCompilationContext2.CreateQueryExecutor[TResult](Expression query)
D:\git\EntityFrameworkCore\src\EFCore\Storage\Database.cs(97,0): at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery2[TResult](Expression query, Boolean async)
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\QueryCompiler.cs(118,0): at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\QueryCompiler.cs(151,0): at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\CompiledQueryCache.cs(84,0): at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\CompiledQueryCache.cs(59,0): at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\QueryCompiler.cs(147,0): at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\EntityQueryProvider.cs(99,0): at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
D:\git\EntityFrameworkCore\src\EFCore\Query\Internal\EntityQueryable`.cs(111,0): at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator()
D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncEnumerableHelpers.cs(46,0): at System.Collections.Generic.AsyncEnumerableHelpers.ToArrayWithLength[T](IAsyncEnumerable`1 source, CancellationToken cancellationToken)
   at System.Collections.Generic.AsyncEnumerableHelpers.ToArray[T](IAsyncEnumerable`1 source, CancellationToken cancellationToken)
D:\git\EntityFrameworkCore\test\EFCore.Specification.Tests\TestUtilities\QueryAsserter.cs(349,0): at Microsoft.EntityFrameworkCore.TestUtilities.QueryAsserter`1.AssertQuery[TItem1](Func`2 actualQuery, Func`2 expectedQuery, Func`2 elementSorter, Action`2 elementAsserter, Boolean assertOrder, Int32 entryCount, Boolean isAsync, String testMethodName)
D:\git\EntityFrameworkCore\test\EFCore.SqlServer.FunctionalTests\Query\GearsOfWarQuerySqlServerTest.cs(7202,0): at Microsoft.EntityFrameworkCore.Query.GearsOfWarQuerySqlServerTest.Select_subquery_projecting_single_constant_null_of_non_mapped_type(Boolean isAsync)
closed-fixed type-bug

Most helpful comment

This exception is also thrown when mapping models with ternary operator.

var dtoList = await products.Select(p => new ProductDTO
{
    Id = p.Id,
    Name = p.Name,
    BrandId = p.BrandId,
    CategoryId = p.CategoryId,
    CountryId = p.CountryId,
    Character = p.Character,
    Description = p.Description,
    Image = p.Image,
    Price = p.Price,
    Weight = p.Weight,
    Removed = p.Removed,
    Brand = p.Brand == null ? null : new BrandDTO
    {
        Id = p.Brand.Id,
        Name = p.Brand.Name
    },
    Category = p.Category == null ? null : new CategoryDTO
    {
        Id = p.Category.Id,
        Name = p.Category.Name
    },
    Country = p.Country == null ? null : new CountryDTO
    {
        Id = p.Country.Id,
        Name = p.Country.Name
    }
}).OrderBy(p => p.Id).Skip(skip).Take(pageSize).ToArrayAsync();

All 4 comments

FYI I just hit this trying to use preview6 in the Conference Planner workshop app. Offending query is at https://github.com/dotnet-presentations/aspnetcore-app-workshop/blob/3.0/src/BackEnd/Controllers/SessionsController.cs#L27 and includes a call to helper method at https://github.com/dotnet-presentations/aspnetcore-app-workshop/blob/3.0/src/BackEnd/Infrastructure/EntityExtensions.cs#L7

The error shown at first is simply a default InvalidOperationException. If you inline the extension method body into the original query though, you get the "Null TypeMapping in Sql Tree" error. Then, if you comment out the lines of the query that deal with nullable types, it works, e.g.:

[HttpGet]
public async Task<ActionResult<List<SessionResponse>>> Get()
{
    var sessions = await _db.Sessions.AsNoTracking()
                                        .Include(s => s.Track)
                                        .Include(s => s.SessionSpeakers)
                                        .ThenInclude(ss => ss.Speaker)
                                        .Select(session => new ConferenceDTO.SessionResponse
                                                            {
                                                                Id = session.Id,
                                                                Title = session.Title,
                                                                //StartTime = session.StartTime,
                                                                //EndTime = session.EndTime,
                                                //               Speakers = session.SessionSpeakers?
                                                //.Select(ss => new ConferenceDTO.Speaker
                                                //{
                                                //    Id = ss.SpeakerId,
                                                //    Name = ss.Speaker.Name
                                                //})
                                                // .ToList(),
                                                                //TrackId = session.TrackId,
                                                                //Track = new ConferenceDTO.Track
                                                                //{
                                                                //    //Id = session?.TrackId ?? 0,
                                                                //    //Name = session.Track?.Name
                                                                //},
                                                                Abstract = session.Abstract
                                                            })
                                        .ToListAsync();
    return sessions;
}

Any update on this one?

While the exception message is the same, it is quite different scenario.
Collection support is being tracked in #15611 and almost complete (see PR #16312)

This exception is also thrown when mapping models with ternary operator.

var dtoList = await products.Select(p => new ProductDTO
{
    Id = p.Id,
    Name = p.Name,
    BrandId = p.BrandId,
    CategoryId = p.CategoryId,
    CountryId = p.CountryId,
    Character = p.Character,
    Description = p.Description,
    Image = p.Image,
    Price = p.Price,
    Weight = p.Weight,
    Removed = p.Removed,
    Brand = p.Brand == null ? null : new BrandDTO
    {
        Id = p.Brand.Id,
        Name = p.Brand.Name
    },
    Category = p.Category == null ? null : new CategoryDTO
    {
        Id = p.Category.Id,
        Name = p.Category.Name
    },
    Country = p.Country == null ? null : new CountryDTO
    {
        Id = p.Country.Id,
        Name = p.Country.Name
    }
}).OrderBy(p => p.Id).Skip(skip).Take(pageSize).ToArrayAsync();
Was this page helpful?
0 / 5 - 0 ratings