Skip to content

GroupBySplitQueryingEnumerable not disposing related data readers #34280

Open
@invdev-rh

Description

@invdev-rh

Description

I'm working with the DbCommandInterceptor to track some bits around DataReaderClosing and I am getting different results when the query is for GroupBySplitQueryingEnumerable than I do when it's for SplitQueryingEnumerable.

The GroupBy version does not appear to directly dispose of the data reader(s) that are held by the SplitQueryResultCoordinator (_resultCoordinator).

This means a lack of call to the DataReaderClosing method on the DbCommandInterceptor at least for a time (unable to get it to work in my scenario).
When dealing with other enumerable types so far seems consistent and very timely, but the GroupBy version is different. (same looks true for it's Async dispose method)

Inclusive of it not being called the same way, I would like to highlight a potential for these related data readers to not be disposed correctly, can you check that?

Here is the disposal code for GroupBySplitQueryingEnumerable which does not dispose the related data readers

Here is the disposal code for SplitQueryingEnumerable which iterates the data readers on the SplitQueryResultCoordinator and disposes of each

Example code to force the dispose in my app

// some random query for an example
var grpByQuery = context.Users
	.Include(x => x.Addresses)
	.GroupBy(x => x.Age)
	.AsSplitQuery();

using var enumerator = grpByQuery.GetEnumerator();
while (enumerator.MoveNext())
{
    // trigger the enumerable to do it's querying
    // and that will also boot up the _resultCoordinator shown below
}
// stick a dispose of the enumerator in here, it doesn't close all readers

// this code will do the missing parts that the dispose method could/should do
if (enumerator.GetType()
    .GetField("_resultCoordinator", BindingFlags.NonPublic | BindingFlags.Instance)?
    .GetValue(enumerator) is SplitQueryResultCoordinator coordinator)
{
    foreach (var dataReader in coordinator.DataReaders)
    {
        dataReader?.DataReader.Dispose();
    }
    coordinator.DataReaders.Clear();
}

Include provider and version information

EF Core version: 8.0.4
Database provider: (e.g. Microsoft.EntityFrameworkCore.Sqlite)
Target framework: 8.0
Operating system: Windows 11 Pro
IDE: Rider 2024.1.4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions