ReadAsync problem on initialization same DBContext twice

Hi,

I have problem with ReadAsync when using DataManager with same DbContext on two separate Schedulers.

My function look like this :

        public async Task<IEnumerable<WnioskiForm>> Get(DateTime startDate, DateTime endDate)
        {
            var grafikForms = await this.mainContext.WnioskiForms
                .Where(e => e.StartTime <= endDate && e.EndTime >= startDate)
                .ToListAsync().ConfigureAwait(true);


            List<WnioskiForm> eventData = new List<WnioskiForm>();


            foreach (var grafikForm in grafikForms)
            {
                eventData.Add(new WnioskiForm
                {
                    Id = grafikForm.Id,
                    StartTime = grafikForm.StartTime,
                    EndTime = grafikForm.EndTime,
                    RequestId = grafikForm.RequestId,
                    Description = grafikForm.Description,
                    IDD = grafikForm.IDD,
                    IDS = grafikForm.IDS,
                    IloscDni = grafikForm.IloscDni,
                    IsAllDay = grafikForm.IsAllDay,
                    PRI_PraId = grafikForm.PRI_PraId,
                    DZL_DzlId = grafikForm.DZL_DzlId,
                    RecurrenceID = grafikForm.RecurrenceID,
                    RecurrenceRule = grafikForm.RecurrenceRule,
                    RecurrenceException = grafikForm.RecurrenceException,
                    Stan = grafikForm.Stan,
                    Status = grafikForm.Status,
                    CreatedBy = grafikForm.CreatedBy,
                    Color = grafikForm.Color,
                    Style = grafikForm.Style,
                });
            }
            return eventData;
        }


        public async Task<IEnumerable<GrafikForm>> Get(DateTime startDate, DateTime endDate)
        {
            var grafikForms = await this.mainContext.GrafikForms
            .Where(e => e.StartTime <= endDate && e.EndTime >= startDate)
            .ToListAsync().ConfigureAwait(true);


            DateTime selectedDate = DateTime.UtcNow.ToLocalTime();


            List<GrafikForm> eventData = new List<GrafikForm>();


            foreach (var grafikForm in grafikForms)
            {
                eventData.Add(new GrafikForm
                {
                    Id = grafikForm.Id,
                    StartTime = grafikForm.StartTime,
                    EndTime = grafikForm.EndTime,
                    LocationId = grafikForm.LocationId,
                    Description = grafikForm.Description,
                    IsAllDay = grafikForm.IsAllDay,
                    PRI_PraId = grafikForm.PRI_PraId,
                    DZL_DzlId = grafikForm.DZL_DzlId,
                    RecurrenceID = grafikForm.RecurrenceID,
                    RecurrenceRule = grafikForm.RecurrenceRule,
                    RecurrenceException = grafikForm.RecurrenceException,
                    Stan = grafikForm.Stan,
                    Status = grafikForm.Status,
                    CreatedBy = grafikForm.CreatedBy,
                    Color = grafikForm.Color,
                    Style = grafikForm.Style,
                });
            }
            return eventData;
        }


And ReadAsync function in separe Adaptors


public override async Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null)
{
    System.Collections.Generic.IDictionary<string, object> @params = dataManagerRequest.Params;
    DateTime start = DateTime.Parse((string)@params["StartDate"]);
    DateTime end = DateTime.Parse((string)@params["EndDate"]);
    var eventData = await this.appService.Get(start, end);
    return dataManagerRequest.RequiresCounts ? new DataResult() : eventData;
}


I get this error in Log, it work after some page refreshes but its not good thing.

07-03-2024 00:05:37 [Error] [Microsoft.EntityFrameworkCore.Query] An exception occurred while iterating over the results of a query for context type '"SoftlandERPGrafik.Data.DB.MainContext"'."
""System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()"
System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
07-03-2024 00:05:37 [Information] [Serilog.AspNetCore.RequestLoggingMiddleware] HTTP "POST" "/_blazor" responded 200 in 0.1303 ms
07-03-2024 00:05:37 [Warning] [Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer] Unhandled exception rendering component: "A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913."
System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at SoftlandERPGrafik.Core.Repositories.Repository`1.GetAllAsync() in C:\Users\BWL.SOFTLAND20\Source\Repos\Egzennn\SoftlandERPGrafik\SoftlandERPGrafik.Core\Repositories\Repository.cs:line 23
   at SoftlandERPGrafik.Web.Components.Services.BaseService.GetStanAsync() in C:\Users\BWL.SOFTLAND20\Source\Repos\Egzennn\SoftlandERPGrafik\SoftlandERPGrafik.Web\Components\Services\BaseService.cs:line 78
   at SoftlandERPGrafik.Web.Components.Pages.Wnioski.OnInitializedAsync() in C:\Users\BWL.SOFTLAND20\Source\Repos\Egzennn\SoftlandERPGrafik\SoftlandERPGrafik.Web\Components\Pages\Wnioski.razor.cs:line 74
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
07-03-2024 00:05:37 [Information] [Serilog.AspNetCore.RequestLoggingMiddleware] HTTP "GET" "/_blazor" responded 200 in 0.1425 ms
07-03-2024 00:05:37 [Error] [Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost] Unhandled exception in circuit '"BVyw22PsfBhfDO6GelRXVjfD3HDj62r5kTi4OeT7qU4"'.
System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at SoftlandERPGrafik.Core.Repositories.Repository`1.GetAllAsync() in C:\Users\BWL.SOFTLAND20\Source\Repos\Egzennn\SoftlandERPGrafik\SoftlandERPGrafik.Core\Repositories\Repository.cs:line 23
   at SoftlandERPGrafik.Web.Components.Services.BaseService.GetStanAsync() in C:\Users\BWL.SOFTLAND20\Source\Repos\Egzennn\SoftlandERPGrafik\SoftlandERPGrafik.Web\Components\Services\BaseService.cs:line 78
   at SoftlandERPGrafik.Web.Components.Pages.Wnioski.OnInitializedAsync() in C:\Users\BWL.SOFTLAND20\Source\Repos\Egzennn\SoftlandERPGrafik\SoftlandERPGrafik.Web\Components\Pages\Wnioski.razor.cs:line 74
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
07-03-2024 00:05:37 [Information] [Serilog.AspNetCore.RequestLoggingMiddleware] HTTP "POST" "/_blazor" responded 200 in 0.1276 ms
07-03-2024 00:05:38 [Information] [Serilog.AspNetCore.RequestLoggingMiddleware] HTTP "GET" "/_blazor" responded 200 in 0.2212 ms
07-03-2024 00:05:38 [Error] [Microsoft.EntityFrameworkCore.Query] An exception occurred while iterating over the results of a query for context type '"SoftlandERPGrafik.Data.DB.MainContext"'."
""System.InvalidOperationException: Invalid attempt to call ReadAsync when reader is closed.
   at Microsoft.Data.Common.ADP.ExceptionWithStackTrace(Exception e)
--- End of stack trace from previous location ---
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()"
System.InvalidOperationException: Invalid attempt to call ReadAsync when reader is closed.
   at Microsoft.Data.Common.ADP.ExceptionWithStackTrace(Exception e)
--- End of stack trace from previous location ---

2 Replies 1 reply marked as answer

B“ Bartek “Egzennn” Wlodarczyk March 11, 2024 02:44 PM UTC

I tested further and i found out that happend when i have resources in my scheduler for my events, so it dont matter for 2 schedules.

When i dont have any resources it work well.

I did separate DbContext for events and its still dont work with resources.


private IEnumerable<OsobaData>? Osoby;
private IEnumerable<ZatrudnieniDzialy>? Dzialy;
public string[] GroupData = new string[] { "Dzialy", "Osoby" };
protected override async Task OnInitializedAsync()
{
    this.Osoby = await this.WnioskiService.GetEmployeesAsync();
    this.Dzialy = await this.WnioskiService.GetDzialyAsync();
}

<ScheduleGroup Resources="@GroupData"></ScheduleGroup>
<ScheduleResources>
                        <ScheduleResource TValue="int" TItem="ZatrudnieniDzialy" DataSource="@Dzialy" Query="@DepartmanetQuery" Field="DZL_DzlId" Title="Dzialy" Name="Dzialy" TextField="DZL_Kod" IdField="DZL_DzlId" GroupIDField="DZL_ParentId"></ScheduleResource>
                        <ScheduleResource AllowMultiple="true" TValue="int[]" TItem="OsobaData" DataSource="@Osoby" Query="@ResourceQuery" Field="PRI_PraId" Title="Osoby" Name="Osoby" TextField="Imie_Nazwisko" IdField="PRI_PraId" GroupIDField="DZL_DzlId"></ScheduleResource>
</ScheduleResources>

        public async Task<IEnumerable<OsobaData>> GetEmployeesAsync()
        {
            var employees = await this.mainContext.ZatrudnieniZrodlo.ToListAsync();

            return employees.Select(zatrudniony => new OsobaData(zatrudniony)).OrderBy(dzial => dzial.DZL_Kod).ThenBy(osoba => osoba.Imie_Nazwisko).ToList();
        }

        public async Task<IEnumerable<ZatrudnieniDzialy>> GetDzialyAsync()
        {
            return await this.mainContext.ZatrudnieniDzialy.ToListAsync();
        }


RR Ram Raju Elaiyaperumal Syncfusion Team March 19, 2024 03:18 PM UTC

Hi Bartek,

The issue you're facing seems to be related to the asynchronous nature of your data retrieval and the initialization of your scheduler. The scheduler might be getting initialized before your data is fully retrieved, causing the error you're seeing.

Here are two potential solutions:

Solution 1: Use separate custom adaptors for different contexts

By using separate custom adaptors for each context, you can ensure that each context operates independently and doesn't interfere with each other. This can help prevent the issue of both contexts trying to access the data at the same time.

We have prepared a sample, kindly check on the attached sample

Solution 2: Add a null check before the scheduler initialization

Before initializing the scheduler, you can add a null check to ensure that your data has been fully retrieved. If the data is null, you can delay the initialization of the scheduler.

Here's how you can modify your OnInitializedAsync method to include this null check:

protected override async Task OnInitializedAsync()

{

    this.Osoby = await this.WnioskiService.GetEmployeesAsync();

    this.Dzialy = await this.WnioskiService.GetDzialyAsync();

}

 

// In your component rendering method

if (this.Osoby != null && this.Dzialy != null)

{

    <SfSchedule></SfSchedule>

}


In this code, the SfSchedule component will only be rendered once both this.Osoby and this.Dzialy are not null, ensuring that your data has been fully retrieved before the scheduler is initialized.


Regards,

Ram


Attachment: CustomAdaptor_5c9f3d89.zip

Marked as answer
Loader.
Up arrow icon