From 90a8f922b8ee1e73cae4814d2a3558a0a1e492e5 Mon Sep 17 00:00:00 2001 From: Elias Heydrich Date: Fri, 15 Aug 2025 14:39:10 +0200 Subject: [PATCH 1/5] remove unnecessary 'ToList()'-calls that serve no purpose --- SqlKata.Execution/QueryFactory.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/SqlKata.Execution/QueryFactory.cs b/SqlKata.Execution/QueryFactory.cs index 5ff399aa..df85e02b 100644 --- a/SqlKata.Execution/QueryFactory.cs +++ b/SqlKata.Execution/QueryFactory.cs @@ -671,8 +671,7 @@ private static IEnumerable handleIncludes(Query query, IEnumerable resu var dynamicResult = result .Cast>() - .Select(x => new Dictionary(x, StringComparer.OrdinalIgnoreCase)) - .ToList(); + .Select(x => new Dictionary(x, StringComparer.OrdinalIgnoreCase)); foreach (var include in query.Includes) { @@ -697,9 +696,7 @@ private static IEnumerable handleIncludes(Query query, IEnumerable resu include.ForeignKey = table.Singularize(false) + "Id"; } - var localIds = dynamicResult.Where(x => x[include.LocalKey] != null) - .Select(x => x[include.LocalKey].ToString()) - .ToList(); + var localIds = dynamicResult.Where( x => x[include.LocalKey] != null ).Select( x => x[include.LocalKey].ToString() ); if (!localIds.Any()) { From a89ff0f970228d14833c91470e01b11453806b1d Mon Sep 17 00:00:00 2001 From: Elias Heydrich Date: Fri, 15 Aug 2025 14:39:40 +0200 Subject: [PATCH 2/5] add new method 'GetUnbuffered' --- SqlKata.Execution/QueryFactory.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/SqlKata.Execution/QueryFactory.cs b/SqlKata.Execution/QueryFactory.cs index df85e02b..0ab2090a 100644 --- a/SqlKata.Execution/QueryFactory.cs +++ b/SqlKata.Execution/QueryFactory.cs @@ -72,6 +72,23 @@ public Query FromQuery(Query query) return xQuery; } + public IEnumerable GetUnbuffered( Query query, IDbTransaction transaction = null, int? timeout = null ) + { + var compiled = CompileAndLog( query ); + + var result = this.Connection.Query( + compiled.Sql, + compiled.NamedBindings, + transaction: transaction, + buffered: false, + commandTimeout: timeout ?? this.QueryTimeout + ); + + result = handleIncludes( query, result ); + + return result; + } + public IEnumerable Get(Query query, IDbTransaction transaction = null, int? timeout = null) { var compiled = CompileAndLog(query); From b13dcaec757ddbbd1d84acf3cc94ed6733c2ed5f Mon Sep 17 00:00:00 2001 From: Elias Heydrich Date: Tue, 26 Aug 2025 11:58:15 +0200 Subject: [PATCH 3/5] updated code with a simpler and cleaner one --- SqlKata.Execution/QueryFactory.cs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/SqlKata.Execution/QueryFactory.cs b/SqlKata.Execution/QueryFactory.cs index 0ab2090a..1287a56a 100644 --- a/SqlKata.Execution/QueryFactory.cs +++ b/SqlKata.Execution/QueryFactory.cs @@ -72,10 +72,23 @@ public Query FromQuery(Query query) return xQuery; } - public IEnumerable GetUnbuffered( Query query, IDbTransaction transaction = null, int? timeout = null ) + /// + /// Executes an unbuffered without reading all results to memory at the same time. + /// (Does not call or similar on the result.) + /// The execution of a with is NOT supported this way. + /// IMPORTANT: The returned *MUST* be fully iterated over by the caller to free underlying allotted resources. + /// If this does not occur, subsequent queries will fail (especially if the underlying DB does not support multiple result sets). + /// + /// if has + public IEnumerable GetUnbuffered(Query query, IDbTransaction transaction = null, int? timeout = null) { - var compiled = CompileAndLog( query ); + var compiled = CompileAndLog(query); + if(query.Includes.Count != 0) + { + throw new InvalidOperationException($"{nameof( GetUnbuffered )} does not support {nameof( Query )} execution with {nameof( query.Includes )}."); + } + var result = this.Connection.Query( compiled.Sql, compiled.NamedBindings, @@ -84,8 +97,6 @@ public IEnumerable GetUnbuffered( Query query, IDbTransaction transaction commandTimeout: timeout ?? this.QueryTimeout ); - result = handleIncludes( query, result ); - return result; } @@ -688,7 +699,8 @@ private static IEnumerable handleIncludes(Query query, IEnumerable resu var dynamicResult = result .Cast>() - .Select(x => new Dictionary(x, StringComparer.OrdinalIgnoreCase)); + .Select(x => new Dictionary(x, StringComparer.OrdinalIgnoreCase)) + .ToList(); foreach (var include in query.Includes) { @@ -713,9 +725,11 @@ private static IEnumerable handleIncludes(Query query, IEnumerable resu include.ForeignKey = table.Singularize(false) + "Id"; } - var localIds = dynamicResult.Where( x => x[include.LocalKey] != null ).Select( x => x[include.LocalKey].ToString() ); + var localIds = dynamicResult.Where(x => x[include.LocalKey] != null) + .Select(x => x[include.LocalKey].ToString()) + .ToList(); - if (!localIds.Any()) + if(!localIds.Any()) { continue; } From 280a03bcb1ac9e91d686fb56a531d53453054c5e Mon Sep 17 00:00:00 2001 From: Elias Heydrich Date: Tue, 26 Aug 2025 11:59:40 +0200 Subject: [PATCH 4/5] bring format in line with original author --- SqlKata.Execution/QueryFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SqlKata.Execution/QueryFactory.cs b/SqlKata.Execution/QueryFactory.cs index 1287a56a..1a9afe15 100644 --- a/SqlKata.Execution/QueryFactory.cs +++ b/SqlKata.Execution/QueryFactory.cs @@ -729,7 +729,7 @@ private static IEnumerable handleIncludes(Query query, IEnumerable resu .Select(x => x[include.LocalKey].ToString()) .ToList(); - if(!localIds.Any()) + if (!localIds.Any()) { continue; } From 8f378246ec0a58ed656be4eda5cb73ff580a6216 Mon Sep 17 00:00:00 2001 From: Elias Heydrich Date: Tue, 26 Aug 2025 12:02:33 +0200 Subject: [PATCH 5/5] cleaned-up documentation further, limiting the text to the essentials --- SqlKata.Execution/QueryFactory.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SqlKata.Execution/QueryFactory.cs b/SqlKata.Execution/QueryFactory.cs index 1a9afe15..0073d8a7 100644 --- a/SqlKata.Execution/QueryFactory.cs +++ b/SqlKata.Execution/QueryFactory.cs @@ -73,9 +73,8 @@ public Query FromQuery(Query query) } /// - /// Executes an unbuffered without reading all results to memory at the same time. - /// (Does not call or similar on the result.) - /// The execution of a with is NOT supported this way. + /// Executes an unbuffered without reading all results to memory at the same time. + /// The execution of a with is *NOT* supported this way. /// IMPORTANT: The returned *MUST* be fully iterated over by the caller to free underlying allotted resources. /// If this does not occur, subsequent queries will fail (especially if the underlying DB does not support multiple result sets). ///