Skip to content

Improve the Virtualization docs to clarify that placeholder content must be the same size as item content #44430

@Alerinos

Description

@Alerinos

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I used this example from the documentation:
https://learn.microsoft.com/pl-pl/aspnet/core/blazor/components/virtualization?view=aspnetcore-7.0

private async ValueTask<ItemsProviderResult<Employee>> LoadEmployees(
    ItemsProviderRequest request)
{
    var numEmployees = Math.Min(request.Count, totalEmployees - request.StartIndex);
    var employees = await EmployeesService.GetEmployeesAsync(request.StartIndex, 
        numEmployees, request.CancellationToken);

    return new ItemsProviderResult<Employee>(employees, totalEmployees);
}

My code looks like this:

    private async ValueTask<ItemsProviderResult<DTO.Article>> LoadEmployees(ItemsProviderRequest request)
    {
// Count = 336
        var count = await _search._context.Article.CountAsync(x => x.Status == Models.Article.StatusType.Show);
        var numEmployees = Math.Min(request.Count, count - request.StartIndex);
        
        var dto2 = await _search._context.Article
            .Include(x => x.Details)
            .Include(x => x.Names)
            .Include(x => x.Images)
            .Where(x => x.Status == Models.Article.StatusType.Show)
            .OrderByDescending(x => x.Details.Created)
            .Skip(request.StartIndex)
            .Take(numEmployees)
            .ToListAsync();

        var dto3 = dto2.Select(x => new DTO.Article
        {
            Name = x.Names.OrderByDescending(x => x.Created).Select(x => x.Name).FirstOrDefault() ?? string.Empty,
            Title = x.Details.Title,
            Description = x.Details.Description,
            Created = x.Details.Created,
            Tags = x.HashTags.Select(x => x.Tag).Take(3).ToList(),
            ImageHead = x.Images.LastOrDefault(x => x.Type == Image.StatusType.Header).Url ?? string.Empty,
        }).ToList();
        
// dto3 = 35 object
// count = 336 int
        return new ItemsProviderResult<DTO.Article>(dto3, count);
    }

My model:

internal class Article
{
    public Guid Id { get; set; }
    public string Status { get; set; } = string.Empty;
    public string Culture { get; set; } = string.Empty;
    public List<string> Cultures { get; set; } = null!;
    public string Name { get; set; } = string.Empty;
    public string Title { get; set; } = string.Empty;
    public string Content { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public bool Nsfw { get; set; } = false;
    public bool Sponsor { get; set; } = false;
    public bool Logged { get; set; } = false;
    public bool Premium { get; set; } = false;
    public decimal ReadingTime { get; set; }
    public DateTime Created { get; set; } = DateTime.UtcNow;
    public DateTime Updated { get; set; } = DateTime.UtcNow;
    public List<string> Tags { get; set; } = new();
    public string ImageHead { get; set; } = string.Empty;
    public List<Article> Articles { get; set; } = null!;
}

Razor:

<Row Class="gap-y-[1rem] gap-x-[1%]">

    <Virtualize Context="article" ItemsProvider="@LoadEmployees">
        <ItemContent>
            <Column Class="basis-full">
                <Card Title="@article.Title" Link="@($"Article/{article.Name}")" Hover=true>
                    <CardPicture Url="@article.ImageHead" Class="h-[15rem] xl:h-[20rem]" Sizes=@(new List<CardPicture.Size>{ new () { Width = 512, Height = 288 }})/>
                    <CardTitle Class="text-left text-xl"/>
                    <CardContent>
                        <HashTag Tag="@article.Tags" Class="inline"/>
                    <p class="inline text-md text-date dark:text-date_dark float-right">@article.Created.ToString("dd/MM/yy")</p>
                    </CardContent>   
                </Card>
            </Column>
        </ItemContent>
        <Placeholder>
            <Card>
                <CardTitle Title="Loading..."/>
                <CardContent>
                    In progres...
                </CardContent>
            </Card>
        </Placeholder>
    </Virtualize>

</Row>

The first results are correct. The problem starts with scrolling.

First loading, its ok:
image

1 break point scrool:
image

The next one is right away, I don't have to do anything.
image

Scrolls on, 2 break point scroll:
image

Scrolls on, 3 brak point scroll:
image

Still ok, now takes the breakpoint off.

[02:07:20 ERR] An exception occurred while iterating over the results of a query for context type 'Stand.Plugins.Articles.Context'.
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.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
   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.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
[02:07:20 WRN] 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.AspNetCore.Components.Web.Virtualization.Virtualize`1.BuildRenderTree(RenderTreeBuilder builder)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
[02:07:20 ERR] Unhandled exception in circuit '7S3gOiTMV1OjU6v35dYZcg1i2Sb-MZExeXvGsHDWF2Q'.
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.AspNetCore.Components.Web.Virtualization.Virtualize`1.BuildRenderTree(RenderTreeBuilder builder)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

It turns out that everything is happening fast ...
I'm sitting for this half day today. I do not understand what's going on...
There is a documentation error or I don't understand how to do this.
Can I ask for help?

Expected Behavior

No response

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

.net 7 core rc1

Anything else?

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions