EF.Property fails after conditional projection of entity into anonymous type
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
### Bug description
I have a routine that receive an expression that contains a query and it have to apply a projection
Having this semplified DBContext and Model :
```
public class TestContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer("Data Source=DESKTOP-6Q8KE4E\\MSSQLSERVER2022;Integrated Security=SSPI;Initial Catalog=ApplyProjection;Encrypt=False");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity().HasKey(itm => itm.ID);
modelBuilder.Entity().HasKey(itm => itm.ID);
modelBuilder.Entity().HasOne(itm=>itm.Master).WithMany(itm=>itm.Details);
}
}
public class Master
{
public Guid ID { get; set; }
public string Description { get; set; }
public virtual ICollection Details { get; set; }
}
public class Detail
{
public Guid ID { get; set; }
public string Description { get; set; }
public virtual Master Master { get; set; }
}
```
If, for example, I receive this query
```
var q1 = dbContext.Set().Select(itm => itm.Description.Contains("1") ?
new { itm, PropertyA = 1 } :
new { itm, PropertyA = 2 })
```
I can apply this projection :
```
.Select(itm => itm.PropertyA == 1 ?
new { P0 = itm.itm.ID, P1 = "X" } :
new { P0 = itm.itm.ID, P1 = "Y" });
```
so the full query became
```
var q1 = dbContext.Set().Select(itm => itm.Description.Contains("1") ?
new { itm, PropertyA = 1 } :
new { itm, PropertyA = 2 })
.Select(itm => itm.PropertyA == 1 ?
new { P0 = itm.itm.ID, P1 = "X" } :
new { P0 = itm.itm.ID, P1 = "Y" }).ToArray()
```
and this query works.
But if I try to access to a shadow property of the entity :
```
.Select(itm => itm.PropertyA == 1 ?
new { P0 = EF.Property(itm, "MasterID"), P1 = "X" } :
new { P0 = EF.Property(itm, "MasterID"), P1 = "Y" })
```
with this full query :
```
var q2 = dbContext.Set().Select(itm => itm.Description.Contains("1") ?
new { itm, PropertyA = 1 } :
new { itm, PropertyA = 2 })
.Select(itm => itm.PropertyA == 1 ?
new { P0 = EF.Property(itm, "MasterID"), P1 = "X" } :
new { P0 = EF.Property(itm, "MasterID"), P1 = "Y" }).ToArray();
```
this not works with :
```
System.InvalidOperationException
HResult=0x80131509
Message=Translation of 'EF.Property(StructuralTypeShaperExpression(
StructuralType: ConsoleApp1.Detail
ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False).Description.Contains("1") ? new {
itm = StructuralTypeShaperExpression(
StructuralType: ConsoleApp1.Detail
ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False),
PropertyA = 1
} : new {
itm = StructuralTypeShaperExpression(
StructuralType: ConsoleApp1.Detail
ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False),
PropertyA = 2
}, "MasterID")' failed. Either the query source is not an entity type, or the specified property does not exist on the entity type.
Origine=Microsoft.EntityFrameworkCore.Relational
Analisi dello stack:
in Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
in Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
in Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.TranslateInternal(Expression expression, Boolean applyDefaultTypeMapping)
in Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.TranslateProjection(Expression expression, Boolean applyDefaultTypeMapping)
in Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
in Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitNew(NewExpression newExpression)
in Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
in Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitConditional(ConditionalExpression conditionalExpression)
in Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
in Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
in Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
in Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
in Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
in Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
in Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutorExpression[TResult](Expression query)
in Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
in Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
in Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
in Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass11_0`1.b__0()
in Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
in Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteCore[TResult](Expression query, Boolean async, CancellationToken cancellationToken)
in Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
in Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
in Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
in System.Collections.Generic.SegmentedArrayBuilder`1.AddNonICollectionRangeInlined(IEnumerable`1 source)
in System.Linq.Enumerable.g__EnumerableToArray|314_0[TSource](IEnumerable`1 source)
in ConsoleApp1.Program.Main(String[] args) in D:\VM\G\ConsoleApp1\ConsoleApp1\Program.cs: riga 29
```
So, I can access to a model property of the entity but not to a shadow property. Actually the message "Either the query source is not an entity type" seem say that if the source is an entity type I can access to its properties .
So, is it possible to add the option to access also to shadows properties?
### Your code
```csharp
https://github.com/GLuca74/ApplyProjectionAndShadowProperty
```
### Stack traces
```text
```
### Verbose output
```text
```
### EF Core version
9.0.0
### Database provider
_No response_
### Target framework
9.0.0_
### Operating system
Windows 10
### IDE
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.