fail: Microsoft.EntityFrameworkCore.Query[10100]
An exception occurred while iterating over the results of a query for context type 'DBR.Web.Context.DBRContext'.
System.InvalidOperationException: Invalid attempt to call CheckDataIsReady when reader is closed.
at Microsoft.Data.SqlClient.SqlDataReader.CheckDataIsReady(Int32 columnIndex, Boolean allowPartiallyReadColumn, Boolean permitAsync, String methodName)
at Microsoft.Data.SqlClient.SqlDataReader.TryReadColumn(Int32 i, Boolean setTimeout, Boolean allowPartiallyReadColumn)
at Microsoft.Data.SqlClient.SqlDataReader.ReadColumn(Int32 i, Boolean setTimeout, Boolean allowPartiallyReadColumn)
at Microsoft.Data.SqlClient.SqlDataReader.GetGuid(Int32 i)
at lambda_method340(Closure , QueryContext , DbDataReader , ResultContext , SplitQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
System.InvalidOperationException: Invalid attempt to call CheckDataIsReady when reader is closed.
at Microsoft.Data.SqlClient.SqlDataReader.CheckDataIsReady(Int32 columnIndex, Boolean allowPartiallyReadColumn, Boolean permitAsync, String methodName)
at Microsoft.Data.SqlClient.SqlDataReader.TryReadColumn(Int32 i, Boolean setTimeout, Boolean allowPartiallyReadColumn)
at Microsoft.Data.SqlClient.SqlDataReader.ReadColumn(Int32 i, Boolean setTimeout, Boolean allowPartiallyReadColumn)
at Microsoft.Data.SqlClient.SqlDataReader.GetGuid(Int32 i)
at lambda_method340(Closure , QueryContext , DbDataReader , ResultContext , SplitQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
This exception occur when I try to go to get an object (GetByIdAsync()-method) in ASP.NET Core application (Blazor Server). It's used on a service, and that service call my EntityFramework Repository that uses the method GetByIdAsync(Guid id).
When I remove the asynchronous part of EFRepository: .ToListAsync() to .ToList(), it starts working with no issues. Does anyone know why? I want to keep them asynchronous somehow.
My UI:
protected override async Task OnInitializedAsync()
{
if (CreateOrEdit is not "rediger" && CreateOrEdit is not "opret")
{
errorMessage = "Der er ingenting at se her. :(";
isInvalidPath = true;
return;
}
if (!string.IsNullOrWhiteSpace(WorkshopId))
{
Func<IQueryable<Workshop>, IIncludableQueryable<Workshop, object>> workshopIncludes = workshop => workshop.Include(x => x.Address!);
ResponseDTO<WorkshopDTO> loadedWorkshop = await WorkshopService.GetByIdAsync(Guid.Parse(WorkshopId), isTrackingDisabled: false, includeProperties: workshopIncludes);
if (loadedWorkshop.Success)
{
if (CreateOrEdit is "rediger")
{
workshopToEdit = loadedWorkshop.Content!;
}
else
{
workshopInputModel.Name = loadedWorkshop.Content!.Name;
workshopInputModel.PhoneNumber = loadedWorkshop.Content!.PhoneNumber;
workshopInputModel.AddressInputModel!.Street = loadedWorkshop.Content!.Address!.Street;
workshopInputModel.AddressInputModel!.City = loadedWorkshop.Content!.Address.City;
workshopInputModel.AddressInputModel!.PostCode = loadedWorkshop.Content!.Address.PostCode;
}
}
}
}
My GetByIdAsync Service:
public async Task<ResponseDTO<TOUT>> GetByIdAsync(Guid entityId, bool isTrackingDisabled = true, Func<IQueryable<T>, IIncludableQueryable<T, object>>? includeProperties = null, Expression<Func<T, T>>? selector = null, CancellationToken cancellationToken = default)
{
ResponseDTO<TOUT> responseDTO = await repository.GetByIdAsync(entityId, isTrackingDisabled, includeProperties, selector, cancellationToken);
return responseDTO;
}
My GetByIdAsync EFRepository:
public async Task<ResponseDTO<TOUT>> GetByIdAsync(Guid id, bool isTrackingDisabled = true, Func<IQueryable<T>, IIncludableQueryable<T, object>>? includeProperties = null, Expression<Func<T, T>>? selector = null, CancellationToken cancellationToken = default)
{
try
{
T requestedEntity = (await table.QueryHelper(selector: selector, includeProperties: includeProperties, isTrackingDisabled: isTrackingDisabled).ToListAsync(cancellationToken)).Find(entity => (Guid)entity.GetType().GetProperty("Id")!.GetValue(entity)! == id) ?? throw new ArgumentNullException(null);
TOUT requestedEntityDTO = mapper.Map<TOUT>(requestedEntity);
return new ResponseDTO<TOUT> { Success = true, Content = requestedEntityDTO };
}
catch (ArgumentNullException ex)
{
return new ResponseDTO<TOUT> { Success = false, ErrorMessage = $"Din anmodning blev ikke fundet - prøv igen.", ExceptionMessage = ex.Message, InnerExceptionMessage = ex.InnerException?.Message, ErrorType = ErrorType.EntityNotFound };
}
catch (OperationCanceledException ex)
{
return new ResponseDTO<TOUT> { Success = false, ErrorMessage = "Din anmodning blev annulleret.", ExceptionMessage = ex.Message, InnerExceptionMessage = ex.InnerException?.Message, ErrorType = ErrorType.CancellationTokenRequested };
}
catch (Exception ex)
{
return new ResponseDTO<TOUT> { Success = false, ErrorMessage = "Ubehandlet serverfejl. Kontakt server administrator.", ExceptionMessage = ex.Message, InnerExceptionMessage = ex.InnerException?.Message, ErrorType = ErrorType.Unhandled };
}
}
My QueryHelper (extension method):
public static IQueryable<T> QueryHelper<T>(this DbSet<T> table, bool isTrackingDisabled = true, Func<IQueryable<T>, IIncludableQueryable<T, object>>? includeProperties = null, Expression<Func<T, bool>>? filter = null, Expression<Func<T, T>>? selector = null, Func<IQueryable<T>, IOrderedQueryable<T>>? orderBy = null) where T : class
{
IQueryable<T> query = table.AsSplitQuery();
if (isTrackingDisabled)
{
query = query.AsNoTracking();
}
if (filter is not null)
{
query = query.Where(filter);
}
if (includeProperties is not null)
{
query = includeProperties(query);
}
if (selector is not null)
{
query = query.Select(selector);
}
if (orderBy is not null)
{
query = orderBy(query);
}
return query;
}
My 'Workshop' domain model:
public class Workshop : BaseEntity
{
[StringLength(50)]
public string Name { get; set; } = null!;
public Guid AddressId { get; set; }
[ForeignKey(nameof(AddressId))]
public Address? Address { get; set; }
[StringLength(15)]
public string PhoneNumber { get; set; } = null!;
public ICollection<Member>? Members { get; set; }
public ICollection<Case>? Cases { get; set; }
public ICollection<Specialization>? Specializations { get; set; }
}
My 'Address' domain model:
public class Address : BaseEntity
{
[StringLength(50)]
public string Street { get; set; } = null!;
[StringLength(25)]
public string City { get; set; } = null!;
[Required]
public short? PostCode { get; set; }
}
My DBRContext in Program.cs:
builder.Services.AddDbContext<DBRContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DBRContext") ?? throw new InvalidOperationException("Connectionstring 'DBRContext' was not found."), options => options.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)));