Skip to content

Fall out from #36502 #36550

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Fall out from #36502 #36550

wants to merge 9 commits into from

Conversation

cincuranet
Copy link
Contributor

No description provided.

@cincuranet cincuranet marked this pull request as ready for review August 13, 2025 19:15
@cincuranet cincuranet requested a review from a team as a code owner August 13, 2025 19:15
@cincuranet cincuranet requested a review from roji August 13, 2025 19:15
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM modulo some nits!

new ProjectionBindingExpression(_selectExpression, _projectionMembers.Peek(), typeof(ValueBuffer)));
#pragma warning disable EF1001
// This is to handle have correct type for the shaper expression. It is later fixed in MatchTypes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// This is to handle have correct type for the shaper expression. It is later fixed in MatchTypes.
// This is to handle have correct type for the shaper expression. It is later fixed in MatchTypes.
// This mirrors for structural types what we do for scalars.

/// Changes the <see cref="Type" /> of this expression to be nullable.
/// </summary>
[EntityFrameworkInternal]
public virtual void MakeTypeNullable()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming nit: we try to use ClrType to refer to the .NET type, to avoid confusion with EF model structural types (the Type property just above comes from .NET LINQ, which is why it doesn't have the Clr prefix). Can you please add that to the new methods and private variable?

@@ -371,8 +371,13 @@ protected override Expression VisitExtension(Expression extensionExpression)

_projectionMapping[_projectionMembers.Peek()] = projection;

return shaper.Update(
var result = shaper.Update(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: any particular reason to not make MakeTypeNullable(), to simplify the code here (and replace the switch in MatchTypes with a conditional)?

}

private void AddInitializeExpressions(
HashSet<IPropertyBase> properties,
ParameterBindingInfo bindingInfo,
Expression instanceVariable,
MethodCallExpression valueBufferExpression,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MethodCallExpression valueBufferExpression,
MethodCallExpression getValueBufferExpression,

&& (IsNullable(complexType) || parameters.AllowNullable == true)
structuralType is IComplexType complexType
&& ReadComplexTypeDirectly(complexType)
&& parameters.ClrType.IsNullableType()
? HandleNullableComplexTypeMaterialization(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that HandleNullableComplexTypeMaterialization is only called once, maybe just inline it here? Just have a comment explaining why it's necessary etc.

@@ -681,23 +664,15 @@ private static void CreateServiceInstances(
}
}

private Expression HandleNullableComplexTypeMaterialization(IComplexType complexType, Type clrType, Expression materializeExpression, ParameterBindingInfo bindingInfo)
private Expression HandleNullableComplexTypeMaterialization(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this again, I think it's not quite right for the MaterializerSource to be handling the nullable value type problem... With the current design, the MaterializerSource really seems to be about materializing the structural type, and this logic would be better outside, in the shaper generator.

However, we already have a mess with unclear separation of concerns between the MaterializerSource and the shaper generator - let's leave it at that for now.

/// <param name="QueryTrackingBehavior">
/// The query tracking behavior, or <see langword="null" /> if this materialization is not from a query.
/// </param>
public readonly record struct StructuralTypeMaterializerSourceParameters(
ITypeBase StructuralType,
string InstanceName,
bool? AllowNullable,
Type ClrType,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an assertion in the constructor here that ClrType is either equal to StructuralType.Type, or is a nullable over it? To clear document (and enforce) that there can't be any arbitrary CLR type here.

Another idea is to have another constructor that doesn't accept ClrType as a parameter, and initializes it from StructuralType.ClrType, so that callers only need to specify it when it differs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants