ASP.NET core 6 Blazor Server Virtualizeを使ってみる

ASP.NET core 6 Blazor Server Virtualizeを使ってみる

ASP.NET core 6 Blazor Serverで、レンダリングを表示されている部分のみに適応できる「Virtualize」を使用する手順を記述してます。.NETのバージョンは6を使用してます。

環境

  • OS windows10 pro
  • IDE Visual Studio 2022
  • .NET 6
  • Sql Server 2019

プロジェクト作成

ここでは、「Blazor Server アプリ」を選択してプロジェクトを作成してます。

任意の名前でプロジェクトを作成します。
※ここでは「BlazorApp1」という名前で作成してます。

「.NET6.0」を選択して「作成」ボタンを押下します。

表示データ追加

わかりやすくするためにデータをデフォルトで作成されている「WeatherForecast.cs」「WeatherForecastService.cs」「FetchData.razor」に追加しておきます。

「WeatherForecast.cs」

namespace BlazorApp1.Data
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

        public string? Summary { get; set; }
        public string? Summary1 { get; set; }
        public string? Summary2 { get; set; }
        public string? Summary3 { get; set; }
        public string? Summary4 { get; set; }
        public string? Summary5 { get; set; }
        public string? Summary6 { get; set; }
        public string? Summary7 { get; set; }
        public string? Summary8 { get; set; }
        public string? Summary9 { get; set; }
        public string? Summary10 { get; set; }
        public string? Summary11 { get; set; }
        public string? Summary12 { get; set; }
        public string? Summary13 { get; set; }
        public string? Summary14 { get; set; }
        public string? Summary15 { get; set; }
        public string? Summary16 { get; set; }
        public string? Summary17 { get; set; }
        public string? Summary18 { get; set; }
        public string? Summary19 { get; set; }
        public string? Summary20 { get; set; }
        public string? Summary21 { get; set; }
        public string? Summary22 { get; set; }
        public string? Summary23 { get; set; }
        public string? Summary24 { get; set; }
        public string? Summary25 { get; set; }
        public string? Summary26 { get; set; }
        public string? Summary27 { get; set; }
        public string? Summary28 { get; set; }
        public string? Summary29 { get; set; }
        public string? Summary30 { get; set; }
        public string? Summary31 { get; set; }
        public string? Summary32 { get; set; }
        public string? Summary33 { get; set; }
        public string? Summary34 { get; set; }
        public string? Summary35 { get; set; }
        public string? Summary36 { get; set; }
        public string? Summary37 { get; set; }
        public string? Summary38 { get; set; }
        public string? Summary39 { get; set; }
        public string? Summary40 { get; set; }
        public string? Summary41 { get; set; }
        public string? Summary42 { get; set; }
        public string? Summary43 { get; set; }
        public string? Summary44 { get; set; }
        public string? Summary45 { get; set; }
        public string? Summary46 { get; set; }
        public string? Summary47 { get; set; }
        public string? Summary48 { get; set; }
        public string? Summary49 { get; set; }
        public string? Summary50 { get; set; }
    }
}

「WeatherForecastService.cs」

namespace BlazorApp1.Data
{
    public class WeatherForecastService
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
        {
            return Task.FromResult(Enumerable.Range(1, 5000).Select(index => new WeatherForecast
            {
                Date = startDate.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary1 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary2 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary3 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary4 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary5 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary6 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary7 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary8 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary9 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary10 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary11 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary12 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary13 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary14 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary15 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary16 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary17 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary18 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary19 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary20 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary21 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary22 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary23 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary24 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary25 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary26 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary27 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary28 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary29 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary30 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary31 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary32 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary33 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary34 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary35 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary36 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary37 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary38 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary39 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary40 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary41 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary42 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary43 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary44 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary45 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary46 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary47 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary48 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary49 = Summaries[Random.Shared.Next(Summaries.Length)],
                Summary50 = Summaries[Random.Shared.Next(Summaries.Length)]

            }).ToArray());
        }
    }
}

「FetchData.razor」

@page "/fetchdata"

<PageTitle>Weather forecast</PageTitle>

@using BlazorApp1.Data
@inject WeatherForecastService ForecastService

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from a service.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
 
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                    <td>@forecast.Summary1</td>
                    <td>@forecast.Summary2</td>
                    <td>@forecast.Summary3</td>
                    <td>@forecast.Summary4</td>
                    <td>@forecast.Summary5</td>
                    <td>@forecast.Summary6</td>
                    <td>@forecast.Summary7</td>
                    <td>@forecast.Summary8</td>
                    <td>@forecast.Summary9</td>
                    <td>@forecast.Summary10</td>
                    <td>@forecast.Summary11</td>
                    <td>@forecast.Summary12</td>
                    <td>@forecast.Summary13</td>
                    <td>@forecast.Summary14</td>
                    <td>@forecast.Summary15</td>
                    <td>@forecast.Summary16</td>
                    <td>@forecast.Summary17</td>
                    <td>@forecast.Summary18</td>
                    <td>@forecast.Summary19</td>
                    <td>@forecast.Summary20</td>
                    <td>@forecast.Summary21</td>
                    <td>@forecast.Summary22</td>
                    <td>@forecast.Summary23</td>
                    <td>@forecast.Summary24</td>
                    <td>@forecast.Summary25</td>
                    <td>@forecast.Summary26</td>
                    <td>@forecast.Summary27</td>
                    <td>@forecast.Summary28</td>
                    <td>@forecast.Summary29</td>
                    <td>@forecast.Summary30</td>
                    <td>@forecast.Summary31</td>
                    <td>@forecast.Summary32</td>
                    <td>@forecast.Summary33</td>
                    <td>@forecast.Summary34</td>
                    <td>@forecast.Summary35</td>
                    <td>@forecast.Summary36</td>
                    <td>@forecast.Summary37</td>
                    <td>@forecast.Summary38</td>
                    <td>@forecast.Summary39</td>
                    <td>@forecast.Summary40</td>
                    <td>@forecast.Summary41</td>
                    <td>@forecast.Summary42</td>
                    <td>@forecast.Summary43</td>
                    <td>@forecast.Summary44</td>
                    <td>@forecast.Summary45</td>
                    <td>@forecast.Summary46</td>
                    <td>@forecast.Summary47</td>
                    <td>@forecast.Summary48</td>
                    <td>@forecast.Summary49</td>
                    <td>@forecast.Summary50</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
}

実行

Virtualizeを使用しない状態で実行してみます。

表示されるまで非常に時間がかかっていることがわかります。

Virtualize使用

次に「FetchData.razor」を「Virtualize」を使用して変更してみます。

@page "/fetchdata"

<PageTitle>Weather forecast</PageTitle>

@using BlazorApp1.Data
@inject WeatherForecastService ForecastService

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from a service.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
 
        <tbody>
            <Virtualize Context="forecast" Items="@forecasts">
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                    <td>@forecast.Summary1</td>
                    <td>@forecast.Summary2</td>
                    <td>@forecast.Summary3</td>
                    <td>@forecast.Summary4</td>
                    <td>@forecast.Summary5</td>
                    <td>@forecast.Summary6</td>
                    <td>@forecast.Summary7</td>
                    <td>@forecast.Summary8</td>
                    <td>@forecast.Summary9</td>
                    <td>@forecast.Summary10</td>
                    <td>@forecast.Summary11</td>
                    <td>@forecast.Summary12</td>
                    <td>@forecast.Summary13</td>
                    <td>@forecast.Summary14</td>
                    <td>@forecast.Summary15</td>
                    <td>@forecast.Summary16</td>
                    <td>@forecast.Summary17</td>
                    <td>@forecast.Summary18</td>
                    <td>@forecast.Summary19</td>
                    <td>@forecast.Summary20</td>
                    <td>@forecast.Summary21</td>
                    <td>@forecast.Summary22</td>
                    <td>@forecast.Summary23</td>
                    <td>@forecast.Summary24</td>
                    <td>@forecast.Summary25</td>
                    <td>@forecast.Summary26</td>
                    <td>@forecast.Summary27</td>
                    <td>@forecast.Summary28</td>
                    <td>@forecast.Summary29</td>
                    <td>@forecast.Summary30</td>
                    <td>@forecast.Summary31</td>
                    <td>@forecast.Summary32</td>
                    <td>@forecast.Summary33</td>
                    <td>@forecast.Summary34</td>
                    <td>@forecast.Summary35</td>
                    <td>@forecast.Summary36</td>
                    <td>@forecast.Summary37</td>
                    <td>@forecast.Summary38</td>
                    <td>@forecast.Summary39</td>
                    <td>@forecast.Summary40</td>
                    <td>@forecast.Summary41</td>
                    <td>@forecast.Summary42</td>
                    <td>@forecast.Summary43</td>
                    <td>@forecast.Summary44</td>
                    <td>@forecast.Summary45</td>
                    <td>@forecast.Summary46</td>
                    <td>@forecast.Summary47</td>
                    <td>@forecast.Summary48</td>
                    <td>@forecast.Summary49</td>
                    <td>@forecast.Summary50</td>
                </tr>
            </Virtualize>
        </tbody>
    </table>
}

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
}

実行してみます。

さきほどのように待つ必要がなく、表示されている部分から生成されていることが確認できます。