Blazor中初始化页面并访问数据库以初始化自身的最佳方法是什么?

huangapple go评论69阅读模式
英文:

What is the best way in Blazor to initialize a page that hits the DB to initialize itself

问题

我学到的是,我想在 _Host.cshtml 中设置 render-mode="Server"。这样页面只会渲染一次。

但是... 这也是渲染页面最慢的方式。如果我的 OnInitializedAsync() 中的代码正在访问数据库,那么在我从数据库中读取所有数据之前,页面将不会被渲染。

对于这种情况,在 OnAfterRenderAsync(true) 中读取数据会更好吗?在这种情况下,页面将以没有数据的方式渲染,然后数据将被填充。

至少在我的情况下,对于那些影响布局的变量,例如可见性和启用状态等,我可以在 OnInitializedAsync() 中设置,而不需要访问数据库。因此,一旦我填充数据,表格/网格将增长,但除此之外,只有字段将被填充为其初始数据。

那么在这种情况下通常会做什么呢?

英文:

What I learned in this question is I want to set render-mode="Server" in _Host.cshtml. This way the page is rendered once.

But... this is also the slowest way to render the page. If the code in my OnInitializedAsync() is hitting the DB, then nothing will be rendered until I've read everything from the DB.

For this case, is it better to read in that data in OnAfterRenderAsync(true)? In this case the page will be rendered with no data, and then the data will fill.

And, for my case at least, and variables that impact layout in terms of what's visible, what's enabled, etc. I can set in OnInitializedAsync() without hitting the DB. So tables/grids will grow once I populate the data, but other than that, it would just be fields being populated with their initial data.

So what is normally done in this case?

答案1

得分: 0

双重呈现仅在登录页面上发生,因此您可以选择:

  1. 使页面在活动方面保持轻量。
  2. 检测双重呈现并在第一次呈现中不执行任何数据库工作。

这里有一个答案显示如何使用 IHttpContextAccessor 服务来检测第一次呈现并使用它来修改组件行为。

https://stackoverflow.com/a/75778169/13065781

这是一个演示页面,展示了如何在正常组件生命周期内处理您描述的情况。

请注意,正如我之前指出的,良好的设计 = 不需要诉诸 OnAfterRenderAsync 的修补。个人观点:我的组件不实现 IHandleAfterRender,如果需要它用于 JSInterop,我会根据组件逐个实现它。

@page "/"
@using System.Diagnostics
@inject IHttpContextAccessor HttpContextAccessor

<PageTitle>Index</PageTitle>

@if (_isServerRender)
{
    <div class="alert alert-danger">预加载中</div>
}
else if(_loading)
{
    <div class="alert alert-info">加载中</div>
}
else
{
    <div>
        <h1>你好,世界!</h1>

        欢迎使用你的新应用程序。

        <SurveyPrompt Title="Blazor对你有何作用?" />
    </div>
}


@code {
    public Guid Uid { get; init; } = Guid.NewGuid();
    private bool _loading;
    private bool _isServerRender;

    protected override void OnInitialized()
        => _isServerRender = !(HttpContextAccessor.HttpContext is not null && HttpContextAccessor.HttpContext.Response.HasStarted);

    protected async override Task OnInitializedAsync()
    {
        _loading = true;
        if (_isServerRender)
            return;

        // 模拟大量的异步DB操作
        await Task.Delay(5000);
        _loading = false;
    }
}
英文:

The double render only occurs on the landing page, so you can either:

  1. Keep the page light on activity.
  2. Detect the double render and don't do any DB work in the first render.

There's an answer here that shows how to detect the first render using the IHttpContextAccessor service and use it to modify the component behaviour.

https://stackoverflow.com/a/75778169/13065781

Here's a demo page showing how to handle what you've described within the normal component lifecycle.

Note that, as I've pointed out before, good design = no need to resort to the OnAfterRenderAsync kludge. Personal: My components don't implement IHandleAfterRender, if I need it for JSInterop I implement it on a component by component basis.

@page &quot;/&quot;
@using System.Diagnostics
@inject IHttpContextAccessor HttpContextAccessor

&lt;PageTitle&gt;Index&lt;/PageTitle&gt;

@if (_isServerRender)
{
    &lt;div class=&quot;alert alert-danger&quot;&gt;Pre-Loading&lt;/div&gt;
}
else if(_loading)
{
    &lt;div class=&quot;alert alert-info&quot;&gt;Loading&lt;/div&gt;
}
else
{
    &lt;div&gt;
        &lt;h1&gt;Hello, world!&lt;/h1&gt;

        Welcome to your new app.

        &lt; SurveyPrompt Title = &quot;How is Blazor working for you?&quot; /&gt;
    &lt;/div&gt;
}


@code {
    public Guid Uid { get; init; } = Guid.NewGuid();
    private bool _loading;
    private bool _isServerRender;

    protected override void OnInitialized()
        =&gt; _isServerRender = !(HttpContextAccessor.HttpContext is not null &amp;&amp; HttpContextAccessor.HttpContext.Response.HasStarted);

    protected async override Task OnInitializedAsync()
    {
        _loading = true;
        if (_isServerRender)
            return;

        // emulate a lot of DB async activity
        await Task.Delay(5000);
        _loading = false;
    }
}

答案2

得分: 0

.NET 8 将为 Blazor 服务器引入一个名为“流式渲染”的新功能。这将允许页面在数据加载时进行渲染。

有关更多信息,请查看这篇来自Microsoft的博客文章

你基本上只需要提供一个属性 @attribute [StreamRendering(true)]

@page "/fetchdata"
@using BlazorSSR.Data
@inject WeatherForecastService ForecastService
@attribute [StreamRendering(true)]

<PageTitle>天气预报</PageTitle>

<h1>天气预报</h1>

@if (forecasts is null)
{
    <p><em>加载中...</em></p>
}
else
{
    // 渲染天气预报
}

@code {
    private string message;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
    }
}
英文:

.NET 8 will bring a new feature to Blazor server called Streaming Rendering. This will allow a page to render while the data is loading.

For more information take a look on this blog post from Microsoft.

All you'll need to do basically is to provide an attribute @attribute [StreamRendering(true)]

@page &quot;/fetchdata&quot;
@using BlazorSSR.Data
@inject WeatherForecastService ForecastService
@attribute [StreamRendering(true)]

&lt;PageTitle&gt;Weather forecast&lt;/PageTitle&gt;

&lt;h1&gt;Weather forecast&lt;/h1&gt;

@if (forecasts is null)
{
    &lt;p&gt;&lt;em&gt;Loading...&lt;/em&gt;&lt;/p&gt;
}
else
{
    // Render weather forecasts
}

@code {
    private string message;

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

huangapple
  • 本文由 发表于 2023年6月12日 06:42:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76452794.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定