From 8ef36ad8e7ac195e237811058e6e142e758567e6 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Fri, 13 Mar 2020 17:04:48 -0700 Subject: [PATCH] Query: Materialize keyless entity always if it is not coming from a left join Resolves #19537 --- .../ShapedQueryCompilingExpressionVisitor.cs | 62 ++++++++++++------- .../Query/FromSqlQueryTestBase.cs | 13 ++++ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs index 5f5b756a79f..d55ffd4df5d 100644 --- a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs @@ -401,32 +401,46 @@ private Expression ProcessEntityShaper(EntityShaperExpression entityShaperExpres } else { - expressions.Add( - Expression.IfThen( - primaryKey != null - ? primaryKey.Properties.Select( - p => - Expression.NotEqual( - _entityMaterializerSource.CreateReadValueExpression( - valueBufferExpression, - typeof(object), - p.GetIndex(), - p), - Expression.Constant(null))) - .Aggregate((a, b) => Expression.AndAlso(a, b)) - : entityType.GetProperties() - .Select( - p => - Expression.NotEqual( - _entityMaterializerSource.CreateReadValueExpression( - valueBufferExpression, - typeof(object), - p.GetIndex(), - p), - Expression.Constant(null))) - .Aggregate((a, b) => Expression.OrElse(a, b)), + if (primaryKey != null) + { + + expressions.Add(Expression.IfThen( + primaryKey.Properties.Select( + p => Expression.NotEqual( + _entityMaterializerSource.CreateReadValueExpression( + valueBufferExpression, typeof(object), p.GetIndex(), p), + Expression.Constant(null))) + .Aggregate((a, b) => Expression.AndAlso(a, b)), MaterializeEntity( entityType, materializationContextVariable, concreteEntityTypeVariable, instanceVariable, null))); + } + else + { + if (entityShaperExpression.IsNullable) + { + expressions.Add( + Expression.IfThen( + entityType.GetProperties() + .Select( + p => + Expression.NotEqual( + _entityMaterializerSource.CreateReadValueExpression( + valueBufferExpression, + typeof(object), + p.GetIndex(), + p), + Expression.Constant(null))) + .Aggregate((a, b) => Expression.OrElse(a, b)), + MaterializeEntity( + entityType, materializationContextVariable, concreteEntityTypeVariable, instanceVariable, null))); + } + else + { + expressions.Add( + MaterializeEntity( + entityType, materializationContextVariable, concreteEntityTypeVariable, instanceVariable, null)); + } + } } expressions.Add(instanceVariable); diff --git a/test/EFCore.Relational.Specification.Tests/Query/FromSqlQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/FromSqlQueryTestBase.cs index 9b70e6ac292..85c76e27324 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/FromSqlQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/FromSqlQueryTestBase.cs @@ -966,6 +966,19 @@ public virtual void FromSqlRaw_with_set_operation() Assert.Equal(7, actual.Length); } + [ConditionalFact] + public virtual void Keyless_entity_with_all_nulls() + { + using var context = CreateContext(); + + var actual = context.Set() + .FromSqlRaw(NormalizeDelimitersInRawString("SELECT NULL AS [CustomerID] FROM [Customers] WHERE [City] = 'Berlin'")) + .IgnoreQueryFilters() + .ToArray(); + + Assert.NotNull(Assert.Single(actual)); + } + protected string NormalizeDelimitersInRawString(string sql) => Fixture.TestStore.NormalizeDelimitersInRawString(sql);