【问题标题】:Website not showing data after upgrading to EF 5.0.1/DbContextFactory升级到 EF 5.0.1/DbContextFactory 后网站不显示数据
【发布时间】:2021-04-10 02:55:25
【问题描述】:

我正在编写一个网络应用程序来提交视频以供投票。 因为遇到了线程和数据库的问题,所以我从 core 3.0.1 升级到了 5.0.1

在我使用 services.AddDbContext 之前,它不起作用。现在我正在使用这个:

  services.AddDbContextFactory<LogicDbContext>(
            dbContextOptions => dbContextOptions
                .UseMySql(serverVersion: ServerVersion.AutoDetect(connectionString), connectionString: connectionString)
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors());

我的前端:

@page "/VideoPage"
@using WebProject.Data
@using Google.Apis.YouTube.v3.Data
@using Microsoft.AspNetCore.Identity
@using Microsoft.EntityFrameworkCore.Diagnostics
@using System.Security.Claims
@using Microsoft.AspNetCore.Identity.EntityFrameworkCore
@using Microsoft.EntityFrameworkCore
@inject YoutubeApiService YoutubeApiService;
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@inject VideoManager VideoManager;
@inject VoteManager VoteManager;
@inject ApplicationDbContext _identityContext

<h1>Videos</h1>

<div style="visibility: @(busy?"visible":"hidden")">
    <text>
        Working...
    </text>
</div>

<table class="table table-bordered">
    <thead>
        <tr>
            <th>Thumbnail</th>
            <th>Title</th>
            <th>Channel</th>
            <th>Date</th>
            <th>Submitter</th>
            <th>Votes</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var video in VideosList)
        {
            <tr>
                <td><img src="@video.Thumbnail" alt="Thumbnail not found" width="200" /></td>
                <td><a href="https://www.youtube.com/watch?v=@video.VideoId">@video.Title</a></td>
                <td>@video.ChannelTitle</td>
                <td>@video.PublicationDate?.ToString("dd.MM.yyyy")</td>
                <td>@_identityContext.Users.FirstOrDefault(u => u.Id == video.Submitter)?.UserName</td>
                <td>
                    @(VoteManager.GetVotesAsync(video).Result)
                </td>
            </tr>

        }
    </tbody>
</table>

@code
{
    public List<Videos> VideosList = new List<Videos>();
    public bool busy;

    protected override async void OnInitialized()
    {
        await RefreshList();
    }

    public async Task RefreshList()
    {
        busy = true;
        VideosList = await VideoManager.GetVideosAsync();
        busy = false;
        this.StateHasChanged();
    }
}

投票管理器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using WebProject.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

namespace WebProject.Data
{
    public class VideoManager
    {
        private readonly IDbContextFactory<LogicDbContext> _contextFactory;
        private readonly YoutubeApiService _youtubeApiService;

        public VideoManager(IDbContextFactory<LogicDbContext> contextFactory, YoutubeApiService youtubeApiService)
        {
            _contextFactory = contextFactory;
            _youtubeApiService = youtubeApiService;
        }

        public async Task<List<Videos>> GetVideosAsync()
        {
            
            var videos = new List<Videos>();
            await using (var context = _contextFactory.CreateDbContext())
            {
                videos = await context.Videos.ToListAsync();
            }
            return videos;
        }


    }
}

在更换新版本和使用工厂之前,代码可以获取视频列表并显示出来。

现在,当我进入页面后,会显示“工作中...”消息,然后没有任何反应。在 VS 中调试时(我没有使用 VS 代码)它告诉我 VideoList 实际上已填充。忙也设置为假。 使用 this.StateHasChanged(); 什么都不做。有时整个网站都死机了,我什至无法点击链接。

有什么我没看到的吗?

【问题讨论】:

  • 我在您的代码中发现了一些错误。您有 async void OnInitialized,这是不正确的。您应该覆盖异步任务 OnInitializedAsync()。然后,在确定列表已填充之前,您不应访问 VideoList。我建议你不要初始化它,因为你会为它分配一个新实例。最好将其保留为 null 并仅在 VideoList 有值时才渲染表。
  • 您能解释一下为什么 VideoLists 应该为空吗?是性能问题吗?
  • i ran into problems with threading and databases, 什么问题? EF Core 3.1 没有线程问题。如果您的代码使用错误的访问模式,升级 ORM 将无法修复它们。 DbContext 在设计上是线程安全的。这不是要重用的连接,而是工作单元
  • i was using the services.AddDbContext, wich did not work 什么不起作用?您使用的是哪个 MySQL 提供商?甲骨文的供应商因其错误和有点……延迟更新而臭名昭著。毕竟,Oracle 对支持 .NET Core 没有兴趣。这就是人们改用开源 Pomelo 驱动程序的原因。
  • 更多问题 - async void 用于事件处理程序。 OnInitialized 不是事件处理程序。您需要改用async Task OnInitializedAsync。无法等待 async void 方法,这意味着即使 RefreshList 仍在运行,应用程序也会继续运行。当它完成时,页面已经被渲染并发送到浏览器

标签: entity-framework-core blazor blazor-server-side


【解决方案1】:

问题出在

<td>
  @(VoteManager.GetVotesAsync(video).Result)
</td>

你不能在 Blazor (Razor) 代码中 await.Result 是罪魁祸首,它可以阻塞主线程,导致死锁。这符合你的症状。

规则是始终避免在异步代码中使用.Result.Wait()

作为一种解决方案,只需 .Include() 获得视频时的投票即可。执行 1 个大查询也比许多小查询提供更好的性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    相关资源
    最近更新 更多