diff --git a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs
index 768c68222b9..db0c8bb40cf 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/OrderingExpression.cs
@@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// not used in application code.
///
///
+#if DEBUG
+[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
+#endif
public class OrderingExpression : Expression, IPrintableExpression
{
///
diff --git a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs
index 4a092975ad1..bc1d7becc10 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/ProjectionExpression.cs
@@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// application or provider, then please file an issue at
/// github.com/dotnet/efcore.
///
+#if DEBUG
+[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
+#endif
public sealed class ProjectionExpression : Expression, IPrintableExpression
{
internal ProjectionExpression(SqlExpression expression, string alias)
@@ -57,6 +60,7 @@ public ProjectionExpression Update(SqlExpression expression)
void IPrintableExpression.Print(ExpressionPrinter expressionPrinter)
{
expressionPrinter.Visit(Expression);
+
if (Alias != string.Empty
&& !(Expression is ColumnExpression column
&& column.Name == Alias))
diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
index d515782c6df..7057d01825b 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
@@ -21,6 +21,7 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// an issue at github.com/dotnet/efcore.
///
// Class is sealed because there are no public/protected constructors. Can be unsealed if this is changed.
+[DebuggerDisplay("{PrintShortSql(), nq}")]
public sealed partial class SelectExpression : TableExpressionBase
{
private const string DiscriminatorColumnAlias = "Discriminator";
@@ -4561,6 +4562,13 @@ public override IEnumerable GetAnnotations()
///
protected override void Print(ExpressionPrinter expressionPrinter)
+ {
+ PrintProjections(expressionPrinter);
+ expressionPrinter.AppendLine();
+ PrintSql(expressionPrinter);
+ }
+
+ private void PrintProjections(ExpressionPrinter expressionPrinter)
{
if (_clientProjections.Count > 0)
{
@@ -4588,12 +4596,16 @@ protected override void Print(ExpressionPrinter expressionPrinter)
}
}
}
+ }
- expressionPrinter.AppendLine();
-
- foreach (var tag in Tags)
+ private void PrintSql(ExpressionPrinter expressionPrinter, bool withTags = true)
+ {
+ if (withTags)
{
- expressionPrinter.Append($"-- {tag}");
+ foreach (var tag in Tags)
+ {
+ expressionPrinter.Append($"-- {tag}");
+ }
}
IDisposable? indent = null;
@@ -4682,6 +4694,26 @@ protected override void Print(ExpressionPrinter expressionPrinter)
}
}
+ private string PrintShortSql()
+ {
+ var expressionPrinter = new ExpressionPrinter();
+ PrintSql(expressionPrinter, withTags: false);
+ return expressionPrinter.ToString();
+ }
+
+ ///
+ ///
+ /// Expand this property in the debugger for a human-readable representation of this .
+ ///
+ ///
+ /// Warning: Do not rely on the format of the debug strings.
+ /// They are designed for debugging only and may change arbitrarily between releases.
+ ///
+ ///
+ [EntityFrameworkInternal]
+ public DebugView DebugView
+ => new(PrintShortSql, () => this.Print());
+
///
public override bool Equals(object? obj)
=> obj != null
diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs
index 8301f316dbb..0f11720d4a3 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/SqlExpression.cs
@@ -13,7 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
///
///
#if DEBUG
-[DebuggerDisplay("{new Microsoft.EntityFrameworkCore.Query.ExpressionPrinter().PrintExpression(this), nq}")]
+[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
#endif
public abstract class SqlExpression : Expression, IPrintableExpression
{
diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs
index d535dc2a3ea..07ed28296e1 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs
@@ -12,6 +12,9 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions;
/// not used in application code.
///
///
+#if DEBUG
+[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
+#endif
public abstract class TableExpressionBase : Expression, IPrintableExpression
{
private readonly IReadOnlyDictionary? _annotations;
diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs
index dfee02d5868..5c51f71449c 100644
--- a/src/EFCore/Query/ExpressionPrinter.cs
+++ b/src/EFCore/Query/ExpressionPrinter.cs
@@ -166,16 +166,22 @@ private string PrintCore(Expression expression, int? characterLimit = null, bool
Visit(expression);
- var queryPlan = PostProcess(_stringBuilder.ToString());
+ return ToString();
+ }
+
+ ///
+ public override string ToString()
+ {
+ var printed = PostProcess(_stringBuilder.ToString());
- if (characterLimit is > 0)
+ if (CharacterLimit is > 0)
{
- queryPlan = queryPlan.Length > characterLimit
- ? queryPlan[..characterLimit.Value] + "..."
- : queryPlan;
+ printed = printed.Length > CharacterLimit
+ ? printed[..CharacterLimit.Value] + "..."
+ : printed;
}
- return queryPlan;
+ return printed;
}
///