diff --git a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs
index fabab2bb19d..35499e85961 100644
--- a/src/EFCore.Relational/Query/ISqlExpressionFactory.cs
+++ b/src/EFCore.Relational/Query/ISqlExpressionFactory.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
namespace Microsoft.EntityFrameworkCore.Query;
@@ -454,6 +452,15 @@ public interface ISqlExpressionFactory
/// An expression representing a constant in a SQL tree.
SqlConstantExpression Constant(object? value, Type type, RelationalTypeMapping? typeMapping = null);
+ ///
+ /// Creates a new which represents a SQL token.
+ ///
+ /// A string token to print in SQL tree.
+ /// The of the expression.
+ /// The associated with the expression.
+ /// An expression representing a SQL token.
+ SqlFragmentExpression Fragment(string sql, Type type, RelationalTypeMapping? typeMapping = null);
+
///
/// Creates a new which represents a SQL token.
///
diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs
index 0dbfacce2d1..b6d09d18506 100644
--- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs
+++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs
@@ -64,7 +64,7 @@ public SqlExpressionFactory(SqlExpressionFactoryDependencies dependencies)
ScalarSubqueryExpression e => e.ApplyTypeMapping(typeMapping),
SqlBinaryExpression e => ApplyTypeMappingOnSqlBinary(e, typeMapping),
SqlConstantExpression e => e.ApplyTypeMapping(typeMapping),
- SqlFragmentExpression e => e,
+ SqlFragmentExpression e => e.ApplyTypeMapping(typeMapping),
SqlFunctionExpression e => e.ApplyTypeMapping(typeMapping),
SqlParameterExpression e => e.ApplyTypeMapping(typeMapping),
SqlUnaryExpression e => ApplyTypeMappingOnSqlUnary(e, typeMapping),
@@ -688,6 +688,10 @@ public virtual InExpression In(SqlExpression item, SqlParameterExpression values
public virtual LikeExpression Like(SqlExpression match, SqlExpression pattern, SqlExpression? escapeChar = null)
=> (LikeExpression)ApplyDefaultTypeMapping(new LikeExpression(match, pattern, escapeChar, null));
+ ///
+ public virtual SqlFragmentExpression Fragment(string sql, Type type, RelationalTypeMapping? typeMapping = null)
+ => new(sql, type, typeMapping);
+
///
public virtual SqlFragmentExpression Fragment(string sql)
=> new(sql);
diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs
index bc867cc8b92..deecacea001 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFragmentExpression.cs
@@ -19,7 +19,18 @@ public class SqlFragmentExpression : SqlExpression
///
/// A string token to print in SQL tree.
public SqlFragmentExpression(string sql)
- : base(typeof(string), null)
+ : this(sql, typeof(string), typeMapping: null)
+ {
+ }
+
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// A string token to print in SQL tree.
+ /// The of the expression.
+ /// The associated with the expression.
+ public SqlFragmentExpression(string sql, Type type, RelationalTypeMapping? typeMapping = null)
+ : base(type, typeMapping)
{
Sql = sql;
}
@@ -29,6 +40,14 @@ public SqlFragmentExpression(string sql)
///
public virtual string Sql { get; }
+ ///
+ /// Applies supplied type mapping to this expression.
+ ///
+ /// A relational type mapping to apply.
+ /// A new expression which has supplied type mapping.
+ public virtual SqlFragmentExpression ApplyTypeMapping(RelationalTypeMapping? typeMapping)
+ => new(Sql, Type, typeMapping);
+
///
protected override Expression VisitChildren(ExpressionVisitor visitor)
=> this;
diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs
index ff1abca0724..3ca939a63f0 100644
--- a/src/EFCore/Query/ExpressionPrinter.cs
+++ b/src/EFCore/Query/ExpressionPrinter.cs
@@ -619,7 +619,7 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp
_stringBuilder.Append("new " + memberInitExpression.Type.ShortDisplayName());
var appendAction = memberInitExpression.Bindings.Count > 1 ? (Func)AppendLine : Append;
- appendAction("{ ");
+ appendAction(" { ");
using (_stringBuilder.Indent())
{
for (var i = 0; i < memberInitExpression.Bindings.Count; i++)
@@ -790,7 +790,7 @@ protected override Expression VisitNew(NewExpression newExpression)
}
else
{
- appendAction("{ ");
+ appendAction(" { ");
}
IDisposable? indent = null;