Bug description
The documentation for EF Core split queries states:
"When split query is used, the resultsets of all but the last query are buffered — unless MARS is enabled on SQL Server."
See: https://learn.microsoft.com/en-us/ef/core/performance/efficient-querying#internal-buffering-by-ef
However, this appears to be different from the behavior implied by the current EF Core implementation.
In EF Core 10.x/11.x, SqlServerQueryCompilationContext.IsBuffering is implemented as:
public override bool IsBuffering
=> base.IsBuffering
|| (QuerySplittingBehavior == QuerySplittingBehavior.SplitQuery
&& !_multipleActiveResultSetsEnabled);
Source:
https://github.com/dotnet/efcore/blob/main/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContext.cs
Why this appears inconsistent with the documentation
The documentation says that the resultsets of all but the last query are buffered.
This suggests that if a split query produces only one SQL query/resultset, that resultset should not need to be buffered, because it is the last (and only) resultset.
However, SqlServerQueryCompilationContext.IsBuffering is a query-level flag. It becomes true solely because QuerySplittingBehavior == SplitQuery and MARS is disabled, without considering whether the particular query execution actually has multiple SQL resultsets.
Therefore, even a split query that results in only one SQL query can cause BufferedDataReader to be used.
Expected documentation
Could the documentation be clarified to distinguish between:
- Why split queries may require buffering - all but the last resultset need to be buffered when MARS is disabled; and
- When EF Core's
IsBuffering flag causes BufferedDataReader to be used - currently SplitQuery + MARS disabled is sufficient to set this flag, even if the particular execution has only one resultset.
For example, the documentation could clarify that the implementation may enable buffering for the split-query execution as a whole, rather than only buffering resultsets that are actually followed by another resultset.
Is this behavior intentional?
If it is intentional, I think the documentation should be updated to make the distinction explicit, because the current wording can lead to the expectation that a split query with only one resultset will not incur EF's internal BufferedDataReader buffering.
Your code
Consider a query configured with:
optionsBuilder
.UseSqlServer(connectionString)
.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
with MARS disabled and no retrying execution strategy.
For a query that ultimately produces only one SQL command/resultset:
RetriesOnFailure = false
QuerySplittingBehavior = SplitQuery
MARS = false
SqlServerQueryCompilationContext.IsBuffering => true
As a result, EF Core creates `ReaderColumns` and uses `BufferedDataReader` => data streaming is not working
Stack traces
Verbose output
EF Core version
10.x/11.x
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.net 10
Operating system
Windows 11
IDE
No response
Bug description
The documentation for EF Core split queries states:
See: https://learn.microsoft.com/en-us/ef/core/performance/efficient-querying#internal-buffering-by-ef
However, this appears to be different from the behavior implied by the current EF Core implementation.
In EF Core 10.x/11.x,
SqlServerQueryCompilationContext.IsBufferingis implemented as:Source:
https://github.com/dotnet/efcore/blob/main/src/EFCore.SqlServer/Query/Internal/SqlServerQueryCompilationContext.cs
Why this appears inconsistent with the documentation
The documentation says that the resultsets of all but the last query are buffered.
This suggests that if a split query produces only one SQL query/resultset, that resultset should not need to be buffered, because it is the last (and only) resultset.
However,
SqlServerQueryCompilationContext.IsBufferingis a query-level flag. It becomestruesolely becauseQuerySplittingBehavior == SplitQueryand MARS is disabled, without considering whether the particular query execution actually has multiple SQL resultsets.Therefore, even a split query that results in only one SQL query can cause
BufferedDataReaderto be used.Expected documentation
Could the documentation be clarified to distinguish between:
IsBufferingflag causesBufferedDataReaderto be used - currentlySplitQuery + MARS disabledis sufficient to set this flag, even if the particular execution has only one resultset.For example, the documentation could clarify that the implementation may enable buffering for the split-query execution as a whole, rather than only buffering resultsets that are actually followed by another resultset.
Is this behavior intentional?
If it is intentional, I think the documentation should be updated to make the distinction explicit, because the current wording can lead to the expectation that a split query with only one resultset will not incur EF's internal
BufferedDataReaderbuffering.Your code
Stack traces
Verbose output
EF Core version
10.x/11.x
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.net 10
Operating system
Windows 11
IDE
No response