Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d352388
WIP: Add some tests
JoasE Jan 28, 2026
6490d7b
Copy over files: Use StructuralType where needed in query translation…
JoasE Jan 28, 2026
d9d91d2
Add some more tests
JoasE Jan 28, 2026
003383d
Rewrite some baselines
JoasE Jan 28, 2026
7f7b564
Fix async tests
JoasE Jan 28, 2026
1b4b5cd
WIP: distinct, contains and null
JoasE Jan 29, 2026
bbc3477
Fix test do not explicitly set int ids in base test but use value gen…
JoasE Jan 30, 2026
de6328f
Improve object retrieval for null comparison
JoasE Jan 30, 2026
607a921
Distinct detection
JoasE Jan 30, 2026
0457143
WIP some docs for question
JoasE Jan 31, 2026
5ac80e0
WIP: Match code structure of relational where possible
JoasE Feb 3, 2026
a682368
Merge branch 'main' of https://github.com/dotnet/efcore into feature/…
JoasE Feb 3, 2026
753f31e
Cleanup
JoasE Feb 3, 2026
88c84b6
Rename TypeBase to StructuralType
JoasE Feb 4, 2026
19c1de1
Cleanup and add todo
JoasE Feb 4, 2026
3396b9a
Merge branch 'main' of https://github.com/dotnet/efcore into feature/…
JoasE Feb 9, 2026
a5a8bd4
Implement test
JoasE Feb 9, 2026
3b21620
Remove old unused class
JoasE Feb 9, 2026
7127586
Remove skip on fixed tests
JoasE Feb 9, 2026
82e9b15
Rename test class
JoasE Feb 9, 2026
dd4b3f0
Fix null check structural comparison
JoasE Feb 9, 2026
8126941
Rename field
JoasE Feb 9, 2026
2a96a9b
WIP: Use direct comparison
JoasE Feb 9, 2026
dbd1d17
Use CollectionResultExpression for complex collections
JoasE Feb 10, 2026
ee66c0a
Regenerate test
JoasE Feb 10, 2026
c258b9c
Add test and fix
JoasE Feb 10, 2026
d248623
Add docs
JoasE Feb 10, 2026
b3d68eb
Use property clr type
JoasE Feb 10, 2026
3a19515
Remove bom
JoasE Feb 10, 2026
ddcba7e
Make internal
JoasE Feb 10, 2026
a89891e
Merge branch 'main' of https://github.com/dotnet/efcore into feature/…
JoasE Feb 22, 2026
8a94daa
Improve CollectionResultExpression
JoasE Mar 6, 2026
d7116d1
Add explanation for UsesClientProjection
JoasE Mar 6, 2026
0dcbf4e
Add IEntityType type check for BindNavigation
JoasE Mar 6, 2026
2ebd18c
Align CosmosSqlTranslatingExpressionVisitor.cs more
JoasE Mar 6, 2026
fb75af5
Variable renames and more matching to relational
JoasE Mar 6, 2026
5e2e70f
Merge branch 'main' of https://github.com/dotnet/efcore into feature/…
JoasE Mar 6, 2026
1fb5dbe
Rename variables
JoasE Mar 6, 2026
940dda7
fix typo
JoasE Mar 6, 2026
254631c
Remove unused
JoasE Mar 6, 2026
2af802a
Return a sql expression for VisitTypeBinary and fix in relational aswell
JoasE Mar 6, 2026
1e1b8e9
Fix unreachable exception
JoasE Mar 7, 2026
d01e57d
Add check for entity type in UpdateEntityType
JoasE Mar 7, 2026
a2f97d4
Align VisitMember
JoasE Mar 7, 2026
4108a59
Fix Convert
JoasE Mar 7, 2026
b30a197
Copy over UsesClientProjection in SelectExpression
JoasE Mar 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ public static bool TryExtractArray(
projectedStructuralTypeShaper = shaper;
projection = shaper.ValueBufferExpression;
if (projection is ProjectionBindingExpression { ProjectionMember: { } projectionMember }
&& select.GetMappedProjection(projectionMember) is EntityProjectionExpression entityProjection)
&& select.GetMappedProjection(projectionMember) is StructuralTypeProjectionExpression structuralTypeProjection)
{
projection = entityProjection.Object;
projection = structuralTypeProjection.Object;
}
}
else
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Cosmos/Query/Internal/CosmosAliasManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ protected override Expression VisitExtension(Expression node)
ScalarReferenceExpression reference when aliasRewritingMap.TryGetValue(reference.Name, out var newAlias)
=> new ScalarReferenceExpression(newAlias, reference.Type, reference.TypeMapping),
ObjectReferenceExpression reference when aliasRewritingMap.TryGetValue(reference.Name, out var newAlias)
=> new ObjectReferenceExpression(reference.EntityType, newAlias),
=> new ObjectReferenceExpression(reference.StructuralType, newAlias),

_ => base.VisitExtension(node)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio
var translation = _sqlTranslator.Translate(expression);
if (translation == null)
{
_selectExpression.IndicateClientProjection();
return base.Visit(expression);
}

Expand Down Expand Up @@ -214,11 +215,11 @@ protected override Expression VisitExtension(Expression extensionExpression)

if (_clientEval)
{
var entityProjection = (EntityProjectionExpression)projection;
var structuralTypeProjection = (StructuralTypeProjectionExpression)projection;

return entityShaperExpression.Update(
new ProjectionBindingExpression(
_selectExpression, _selectExpression.AddToProjection(entityProjection), typeof(ValueBuffer)));
_selectExpression, _selectExpression.AddToProjection(structuralTypeProjection), typeof(ValueBuffer)));
}

_projectionMapping[_projectionMembers.Peek()] = projection;
Expand Down Expand Up @@ -303,19 +304,19 @@ protected override Expression VisitMember(MemberExpression memberExpression)
return NullSafeUpdate(innerExpression);
}

var innerEntityProjection = shaperExpression.ValueBufferExpression switch
var innerStructuralTypeProjection = shaperExpression.ValueBufferExpression switch
{
ProjectionBindingExpression innerProjectionBindingExpression
=> (EntityProjectionExpression)_selectExpression.Projection[innerProjectionBindingExpression.Index!.Value].Expression,
=> (StructuralTypeProjectionExpression)_selectExpression.Projection[innerProjectionBindingExpression.Index!.Value].Expression,

// Unwrap EntityProjectionExpression when the root entity is not projected
// Unwrap StructuralTypeProjectionExpression when the root entity is not projected
UnaryExpression unaryExpression
=> (EntityProjectionExpression)((UnaryExpression)unaryExpression.Operand).Operand,
=> (StructuralTypeProjectionExpression)((UnaryExpression)unaryExpression.Operand).Operand,

_ => throw new InvalidOperationException(CoreStrings.TranslationFailed(memberExpression.Print()))
};

var navigationProjection = innerEntityProjection.BindMember(
var navigationProjection = innerStructuralTypeProjection.BindMember(
memberExpression.Member, innerExpression.Type, clientEval: true, out var propertyBase);

if (propertyBase is not INavigation navigation
Expand All @@ -326,10 +327,10 @@ UnaryExpression unaryExpression

switch (navigationProjection)
{
case EntityProjectionExpression entityProjection:
case StructuralTypeProjectionExpression structuralTypeProjection:
return new StructuralTypeShaperExpression(
navigation.TargetEntityType,
Expression.Convert(Expression.Convert(entityProjection, typeof(object)), typeof(ValueBuffer)),
Expression.Convert(Expression.Convert(structuralTypeProjection, typeof(object)), typeof(ValueBuffer)),
nullable: true);

case ObjectArrayAccessExpression objectArrayProjectionExpression:
Expand Down Expand Up @@ -525,16 +526,16 @@ when _collectionShaperMapping.TryGetValue(parameterExpression, out var collectio
return QueryCompilationContext.NotTranslatedExpression;
}

var innerEntityProjection = shaperExpression.ValueBufferExpression switch
var innerStructuralTypeProjection = shaperExpression.ValueBufferExpression switch
{
EntityProjectionExpression entityProjection
=> entityProjection,
StructuralTypeProjectionExpression structuralTypeProjection
=> structuralTypeProjection,

ProjectionBindingExpression innerProjectionBindingExpression
=> (EntityProjectionExpression)_selectExpression.Projection[innerProjectionBindingExpression.Index!.Value].Expression,
=> (StructuralTypeProjectionExpression)_selectExpression.Projection[innerProjectionBindingExpression.Index!.Value].Expression,

UnaryExpression unaryExpression
=> (EntityProjectionExpression)((UnaryExpression)unaryExpression.Operand).Operand,
=> (StructuralTypeProjectionExpression)((UnaryExpression)unaryExpression.Operand).Operand,

_ => throw new InvalidOperationException(CoreStrings.TranslationFailed(methodCallExpression.Print()))
};
Expand All @@ -543,7 +544,7 @@ UnaryExpression unaryExpression
var navigation = _includedNavigations.FirstOrDefault(n => n.Name == memberName);
if (navigation == null)
{
navigationProjection = innerEntityProjection.BindMember(
navigationProjection = innerStructuralTypeProjection.BindMember(
memberName, visitedSource.Type, clientEval: true, out var propertyBase);

if (propertyBase is not INavigation projectedNavigation || !projectedNavigation.IsEmbedded())
Expand All @@ -555,7 +556,7 @@ UnaryExpression unaryExpression
}
else
{
navigationProjection = innerEntityProjection.BindNavigation(navigation, clientEval: true);
navigationProjection = innerStructuralTypeProjection.BindNavigation(navigation, clientEval: true);
}

switch (navigationProjection)
Expand Down
6 changes: 3 additions & 3 deletions src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ public virtual CosmosSqlQuery GetSqlQuery(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override Expression VisitEntityProjection(EntityProjectionExpression entityProjectionExpression)
protected override Expression VisitStructuralTypeProjection(StructuralTypeProjectionExpression structuralTypeProjectionExpression)
{
Visit(entityProjectionExpression.Object);
Visit(structuralTypeProjectionExpression.Object);

return entityProjectionExpression;
return structuralTypeProjectionExpression;
}

/// <summary>
Expand Down
Loading
Loading