Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null checking in anonymous projection #12412

Closed
peterjanto opened this issue Jun 19, 2018 · 7 comments
Closed

Null checking in anonymous projection #12412

peterjanto opened this issue Jun 19, 2018 · 7 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Milestone

Comments

@peterjanto
Copy link

peterjanto commented Jun 19, 2018

Exception message: System.InvalidOperationException: 'No mapping to a relational type can be found for the CLR type 'Expression[]'.'
Stack trace:
   at Microsoft.EntityFrameworkCore.Storage.RelationalTypeMappingSourceExtensions.GetMapping(IRelationalTypeMappingSource typeMappingSource, Type clrType)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.GenerateSqlLiteral(Object value)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.VisitConstant(ConstantExpression constantExpression)
   at System.Linq.Expressions.ConstantExpression.Accept(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.VisitAlias(AliasExpression aliasExpression)
   at Microsoft.EntityFrameworkCore.SqlServer.Query.Sql.Internal.SqlServerQuerySqlGenerator.GenerateProjection(Expression projection)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.GenerateList[T](IReadOnlyList`1 items, Action`1 generationAction, Action`1 joinAction)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.VisitSelect(SelectExpression selectExpression)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.GenerateSql(IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.GetRelationalCommand(IReadOnlyDictionary`2 parameters)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.CorrelateSubquery[TInner,TOut,TCollection](Int32 correlatedCollectionId, INavigation navigation, Func`2 resultCollectionFactory, MaterializedAnonymousObject& outerKey, Boolean tracking, Func`1 correlatedCollectionFactory, Func`3 correlationPredicate)
   at lambda_method(Closure , QueryContext , ValueBuffer )
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at xxxx

Steps to reproduce

public class Partner
{
   public ICollection<Address> Addresses { get; set; }
}

public class Address
{
  public AddressTurnovers Turnovers { get; set; }
}

public class AddressTurnovers
{
   public decimal AmountIn { get; set; }
}

var partners = apiContext.Partners
                .Select(x => new
                {
                    Addresses = x.Addresses.Select(y => new
                    {
                        Turnovers = y.Turnovers == null ? null : new
                        {
                            y.Turnovers.AmountIn
                        },
                    }).ToList()
                }).ToList();

Further technical details

EF Core version: 2.1.1
Database Provider: Microsoft.EntityFrameworkCore.SqlServer 2.1.1
Operating system: WIN10
IDE: Visual Studio 2017 15.7.1

@smitpatel smitpatel self-assigned this Jun 19, 2018
smitpatel added a commit that referenced this issue Jun 19, 2018
… SQL

Issue:
The issue here is, we had projection of kind `nav.Id == null ? null : new { nav.Property }`
When it is single property access, we can remove null check since SQL is null safe.
Same is not true for anonymous type since it has no SQL equivalent.
Anonyous type produces Expression[] in sql translation and we tried to print it out in SQL causing exception.

Fix:
Fix is to skip over NewExpression/MemberInitExpression so that if we encounter those, we don't go inside of them.

Resolves #12412
@smitpatel
Copy link
Contributor

@peterjanto - Thanks for the repro.

smitpatel added a commit that referenced this issue Jun 19, 2018
… SQL

Issue:
The issue here is, we had projection of kind `nav.Id == null ? null : new { nav.Property }`
When it is single property access, we can remove null check since SQL is null safe.
Same is not true for anonymous type since it has no SQL equivalent.
Anonyous type produces Expression[] in sql translation and we tried to print it out in SQL causing exception.

Fix:
Fix is to skip over NewExpression/MemberInitExpression so that if we encounter those, we don't go inside of them.

Resolves #12412
@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jun 20, 2018
@ajcvickers ajcvickers added this to the 2.1.3 milestone Jun 20, 2018
@ajcvickers
Copy link
Member

@smitpatel This issue is approved for patch and the release\2.1 branch is now open for merging. Please ensure:

  • The appropriate changes get into both the release and dev branches
  • Quirking is included for the release branch only

@smitpatel
Copy link
Contributor

Patch fix commit 2821a22
Quirk commit 6106628
dev commit 443d4ec

@peterjanto
Copy link
Author

peterjanto commented Aug 28, 2018

Hello, Thanks for fix ! But when i use something like this

modelBuilder.Entity<Address>().OwnsOne(x => x.Turnovers);

EF core throw this exception:

System.InvalidOperationException
  HResult=0x80131509
  Message=No mapping to a relational type can be found for the CLR type 'object'.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Storage.RelationalTypeMappingSourceExtensions.GetMapping(IRelationalTypeMappingSource typeMappingSource, Type clrType)
   at Microsoft.EntityFrameworkCore.Storage.TypeMaterializationInfo..ctor(Type modelClrType, IProperty property, IRelationalTypeMappingSource typeMappingSource, Int32 index)
   at Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression.<GetMappedProjectionTypes>b__69_0(Expression e)
   at System.Linq.Enumerable.SelectListIterator`2.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression.<GetMappedProjectionTypes>d__69.MoveNext()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.CorrelateSubquery[TInner,TOut,TCollection](Int32 correlatedCollectionId, INavigation navigation, Func`2 resultCollectionFactory, MaterializedAnonymousObject& outerKey, Boolean tracking, Func`1 correlatedCollectionFactory, Func`3 correlationPredicate)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at xxx

Further technical details

EF Core version: 2.1.2
Database Provider: Microsoft.EntityFrameworkCore.SqlServer 2.1.2
Operating system: WIN10
IDE: Visual Studio 2017 15.8.1

@smitpatel smitpatel reopened this Aug 28, 2018
@smitpatel smitpatel removed this from the 2.1.3 milestone Aug 28, 2018
@smitpatel
Copy link
Contributor

This is the SQL which fails

      SELECT [x.Posts].[Id], [x.Posts].[PostTurnOver_Value], [t].[Id], NULL, [x.Posts].[PostTurnOver_Value] AS [Value], [x.Posts].[BlogId]
      FROM [Posts] AS [x.Posts]
      INNER JOIN (
          SELECT [x0].[Id]
          FROM [Blogs] AS [x0]
      ) AS [t] ON [x.Posts].[BlogId] = [t].[Id]
      ORDER BY [t].[Id]

The issue is NULL for which we cannot find mapping.

@ajcvickers
Copy link
Member

ajcvickers commented Aug 29, 2018

@smitpatel to file a new issue.

@smitpatel
Copy link
Contributor

Filed #13157

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Projects
None yet
Development

No branches or pull requests

3 participants