jeudi 22 septembre 2022

System.InvalidOperationException while dynamically enumerating and retrieving .NET6 Entity Framework DbContext DbSet<...>s instances' records

The subject runtime error's location is inside the following code. Please advise how to fix this issue.

using (var ctx = new MyDbContext())
{
    foreach (var entityInfo in ctx.GetEntitiesInfo())
        System.Console.WriteLine($"{entityInfo.Index}. EntityName = {entityInfo.Name}, Records count = {entityInfo.RecordCount}");
}

public static class Extensions
{
    public readonly record struct EntityInfo (int Index, string? Name, int RecordCount);

    public static IEnumerable<EntityInfo> GetEntitiesInfo(this MyDbContext context)
    {
        var dbSetProperties = context.GetDbSetProperties();
        var dbSets = dbSetProperties.Select(x => x.GetValue(context, null)).ToList();
        var index = 0;
        foreach (IQueryable? dbSet in dbSets)
        {
            ++index;
            // Runtime Error happens on next code line on second iteration
            //   when index = 2:
            //
            // System.InvalidOperationException:
            // 'There is already an open DataReader associated with
            //  this Connection which must be closed first
            //-
            dbSet.Load();
            var items = new List<object>();
            var enumerator = dbSet?.GetEnumerator();
            while (enumerator?.MoveNext() == true)
            {
                var item = enumerator.Current;
                items.Add(item);
            }

            yield return new EntityInfo(index, dbSet?.ElementType?.ToString(), items.Count);
        }
    }
    public static IEnumerable<PropertyInfo> GetDbSetProperties(this MyDbContext context)
    {
        foreach (var property in context.GetType().GetProperties())
            if (property?.PropertyType?.FullName?
                .Contains("Microsoft.EntityFrameworkCore.DbSet`") == true)
                     yield return property;
    }
}




Aucun commentaire:

Enregistrer un commentaire