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

Integrate navigation expansion explanations by @smitpatel into source comments #19415

Merged
merged 1 commit into from
Jan 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -15,6 +15,10 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal
{
public partial class NavigationExpandingExpressionVisitor
{
/// <summary>
/// Expands navigations in the given tree for given source.
/// Optionally also expands navigations for includes.
/// </summary>
private class ExpandingExpressionVisitor : ExpressionVisitor
{
private readonly NavigationExpandingExpressionVisitor _navigationExpandingExpressionVisitor;
Expand Down Expand Up @@ -308,6 +312,10 @@ protected Expression ExpandNavigation(
}
}

/// <summary>
/// Expands an include tree. This is separate and needed because we may need to reconstruct parts of
/// <see cref="NewExpression"/> to apply includes.
/// </summary>
private sealed class IncludeExpandingExpressionVisitor : ExpandingExpressionVisitor
{
private readonly bool _isTracking;
Expand Down Expand Up @@ -534,6 +542,10 @@ private Expression ExpandIncludesHelper(Expression root, EntityReference entityR
}
}

/// <summary>
/// <see cref="NavigationExpansionExpression"/> remembers the pending selector so we don't expand
/// navigations unless we need to. This visitor applies them when we need to.
/// </summary>
private sealed class PendingSelectorExpandingExpressionVisitor : ExpressionVisitor
{
private readonly NavigationExpandingExpressionVisitor _visitor;
Expand Down Expand Up @@ -566,6 +578,9 @@ public override Expression Visit(Expression expression)
}
}

/// <summary>
/// Removes custom expressions from tree and converts it to LINQ again.
/// </summary>
private sealed class ReducingExpressionVisitor : ExpressionVisitor
{
public override Expression Visit(Expression expression)
Expand Down Expand Up @@ -628,6 +643,11 @@ public override Expression Visit(Expression expression)
}
}

/// <summary>
/// Marks <see cref="EntityReference"/> as nullable when coming from a left join.
/// Nullability is required to figure out if the navigation from this entity should be a left join or
/// an inner join.
/// </summary>
private sealed class EntityReferenceOptionalMarkingExpressionVisitor : ExpressionVisitor
{
public override Expression Visit(Expression expression)
Expand All @@ -643,6 +663,9 @@ public override Expression Visit(Expression expression)
}
}

/// <summary>
/// Allows self reference of query root inside query filters/defining queries.
/// </summary>
private sealed class SelfReferenceEntityQueryableRewritingExpressionVisitor : ExpressionVisitor
{
private readonly NavigationExpandingExpressionVisitor _navigationExpandingExpressionVisitor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ public virtual void Print(ExpressionPrinter expressionPrinter)
}
}

/// <summary>
/// A tree structure of includes for a given entity type in <see cref="EntityReference"/>.
/// </summary>
protected class IncludeTreeNode : Dictionary<INavigation, IncludeTreeNode>
{
private EntityReference _entityReference;
Expand Down Expand Up @@ -160,6 +163,10 @@ private bool Equals(IncludeTreeNode includeTreeNode)
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), EntityType);
}

/// <summary>
/// Stores information about the current queryable, its source, structure of projection, parameter type etc.
/// This is needed because once navigations are expanded we still remember these to avoid expanding again.
/// </summary>
protected class NavigationExpansionExpression : Expression, IPrintableExpression
{
private readonly List<(MethodInfo OrderingMethod, Expression KeySelector)> _pendingOrderings
Expand Down Expand Up @@ -248,6 +255,11 @@ public virtual void Print(ExpressionPrinter expressionPrinter)
}
}

/// <summary>
/// A leaf node on navigation tree, representing projection structures of
/// <see cref="NavigationExpansionExpression"/>. Contains <see cref="NavigationTreeExpression.Value"/>,
/// which can be <see cref="NewExpression"/> or <see cref="EntityReference"/>.
/// </summary>
protected class NavigationTreeExpression : NavigationTreeNode, IPrintableExpression
{
public NavigationTreeExpression(Expression value)
Expand All @@ -256,6 +268,9 @@ public NavigationTreeExpression(Expression value)
Value = value;
}

/// <summary>
/// Either <see cref="NewExpression"/> or <see cref="EntityReference"/>.
/// </summary>
public virtual Expression Value { get; private set; }

protected override Expression VisitChildren(ExpressionVisitor visitor)
Expand Down Expand Up @@ -285,6 +300,11 @@ public virtual void Print(ExpressionPrinter expressionPrinter)
}
}

/// <summary>
/// A node in navigation binary tree. A navigation tree is a structure of the current parameter, which
/// would be transparent identifier (hence it's a binary structure). This allows us to easily condense to
/// inner/outer member access.
/// </summary>
protected class NavigationTreeNode : Expression
{
private NavigationTreeNode _parent;
Expand Down Expand Up @@ -333,6 +353,10 @@ public virtual Expression GetExpression()
}
}

/// <summary>
/// Owned navigations are not expanded, since they map differently in different providers.
/// This remembers such references so that they can still be treated like navigations.
/// </summary>
protected class OwnedNavigationReference : Expression
{
public OwnedNavigationReference(Expression parent, INavigation navigation, EntityReference entityReference)
Expand Down