@@ -848,7 +848,7 @@ module internal QueryImplementation =
848848 ForeignTable = { Schema= " " ; Name= " " ; Type= " " };
849849 OuterJoin = isOuter; RelDirection = RelationshipDirection.Parents }
850850 SelectMany( sourceAlias, destAlias, LinkQuery( data), outExp)
851- | OptionalOuterJoin( outerJoin, MethodCall( Some(_),( MethodWithName " CreateRelated" ), [ param; _; String PE ; String PK ; String FE ; String FK ; RelDirection dir;])) ->
851+ | OptionalOuterJoin( outerJoin, MethodCall( Some(_),( MethodWithName " CreateRelated" ), [ param; _; String pe ; String pk ; String fe ; String fk ; RelDirection dir;])) ->
852852
853853 let parseKey itm =
854854 SqlColumnType.KeyColumn itm
@@ -857,7 +857,7 @@ module internal QueryImplementation =
857857 | ParamName x -> x
858858 | PropertyGet(_, p) -> Utilities.resolveTuplePropertyName p.Name source.TupleIndex
859859 | _ -> failwith " unsupported parameter expression in CreatedRelated method call"
860- let data = { PrimaryKey = [ parseKey PK ]; PrimaryTable = Table.FromFullName PE ; ForeignKey = [ parseKey FK ]; ForeignTable = Table.FromFullName FE ; OuterJoin = outerJoin; RelDirection = dir }
860+ let data = { PrimaryKey = [ parseKey pk ]; PrimaryTable = Table.FromFullName pe ; ForeignKey = [ parseKey fk ]; ForeignTable = Table.FromFullName fe ; OuterJoin = outerJoin; RelDirection = dir }
861861 let sqlExpression =
862862 match outExp with
863863 | BaseTable( alias, entity) when alias = " " ->
@@ -1350,3 +1350,45 @@ module Seq =
13501350 let stdDevQuery < 'T when 'T : comparison > : System.Linq.IQueryable < 'T > -> 'T = QueryImplementation.getAgg " StdDev"
13511351 /// Execute SQLProvider query to get the variance of elements.
13521352 let varianceQuery < 'T when 'T : comparison > : System.Linq.IQueryable < 'T > -> 'T = QueryImplementation.getAgg " Variance"
1353+
1354+ /// Query debugging and inspection utilities
1355+ module QueryInspection =
1356+
1357+ /// Generates the SQL query string and parameters without executing the query.
1358+ /// Note: This function creates a database connection to access schema metadata for SQL generation,
1359+ /// but does not execute any queries against the database.
1360+ /// This is useful for debugging, logging, or when you need to execute the query through ADO.NET directly.
1361+ /// Returns a tuple of (SQL query string, array of parameter name-value pairs).
1362+ let toQueryString ( query : System.Linq.IQueryable < 'T >) : string * ( string * obj ) array =
1363+ match QueryImplementation.findSqlService query with
1364+ | Some svc, _ ->
1365+ use con = svc.Provider.CreateConnection( svc.DataContext.ConnectionString)
1366+ let ( sql , parameters , _ , _ ) =
1367+ QueryExpression.QueryExpressionTransformer.convertExpression
1368+ svc.SqlExpression
1369+ svc.TupleIndex
1370+ con
1371+ svc.Provider
1372+ false
1373+ ( svc.DataContext.SqlOperationsInSelect = SelectOperations.DatabaseSide)
1374+ let paramArray =
1375+ parameters
1376+ |> Seq.map ( fun p -> p.ParameterName, p.Value)
1377+ |> Seq.toArray
1378+ ( sql, paramArray)
1379+ | None, _ ->
1380+ failwithf " The provided query is not a SQLProvider IQueryable. Type: %s " ( query.GetType() .FullName)
1381+
1382+ /// Extension methods for IQueryable to provide EF Core-like query inspection capabilities
1383+ [<AutoOpen>]
1384+ module IQueryableExtensions =
1385+
1386+ type System.Linq.IQueryable < 'T > with
1387+ /// Generates the SQL query string and parameters without executing the query.
1388+ /// Note: This method creates a database connection to access schema metadata for SQL generation,
1389+ /// but does not execute any queries against the database.
1390+ /// This is useful for debugging, logging, or when you need to execute the query through ADO.NET directly.
1391+ /// Returns a tuple of (SQL query string, array of parameter name-value pairs).
1392+ member this.ToQueryString () : string * ( string * obj ) array =
1393+ toQueryString this
1394+
0 commit comments