Blazor 应用中的数据检索 returns 空数组

Data retrieval in Blazor app returns null-array

我目前正在努力创建我的第一个 Blazor 项目,它应该是一个小型 CRUD 应用程序。我尝试遵循一些教程,但大多数都是过时的发布前教程,并且有许多差异让我感到困惑。

我的问题是我还不了解一些基本概念(尤其是 'services')。当我启动应用程序时,出现以下错误:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

Temporary local of type 'UserManagement.Models.Users[]> was null.

错误发生在 Index.razor 中的“@foreach (var user in users)”行。我会理解没有检索到数据。但是,我的用户 table 中有数据。所以我真的不知道错误可能在这里。

我们目前拥有的是:

Index.razor

@page "/"
@using Models
@using Data
@inject UserService us

<form method="post">
    <input asp-page="/Create" type="button" value="Neuen Benutzer erstellen" />
</form>

<form method="post">
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>UserID</th>
                <th>Name</th>
                <th>Supervisor</th>
                <th>Ersteller</th>
                <th>Erstelldatum</th>
                <th>Optionen</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var user in users)
            {
                <tr>
                    <td>@user.PkId</td>
                    <td>@user.UserId</td>
                    <td>@user.FirstName @user.LastName</td>
                    <td>@user.Supervisor</td>
                    <td>@user.CreationUser</td>
                    <td>@user.CreationDate</td>
                    <td>
                        <a>Delete Account</a><br />
                        <a asp-page="/Edit"> Edit Account</a>
                    </td>
                </tr>
            }
        </tbody>

    </table>
</form>

@code {

    Users[] users;

    protected override async Task OnInitializedAsync()
    {
        users = await us.GetUsersAsync();
    }
}
}

UserService.cs

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using UserManagement.Models;

namespace UserManagement.Data
{
    public class UserService
    {
        private static  UserManagementContext _context;

        public UserService (UserManagementContext context)
        {
            _context = context;
        }

        public async Task<Users[]> GetUsersAsync()
        {
            Users[] u;
            u = await _context.Users.ToArrayAsync();
            return u;

        }
    }
}

型号:Users.cs

using System;
using System.Collections.Generic;

namespace UserManagement.Models
{
    public partial class Users
    {
        public int PkId { get; set; }
        public int FkJobtitle { get; set; }
        public int FkCostcenter { get; set; }
        public int? FkLocation { get; set; }
        public int? FkDepartment { get; set; }
        public int? FkWorkplace { get; set; }
        public int? FkLanguage { get; set; }
        public string UserId { get; set; }
        public string Salutation { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string PersonalId { get; set; }
        public string Supervisor { get; set; }
        public string Telephone { get; set; }
        public DateTime ValidFrom { get; set; }
        public DateTime CreationDate { get; set; }
        public string CreationUser { get; set; }
        public DateTime? ModificationDate { get; set; }
        public string ModificationUser { get; set; }

        public virtual CostCenter FkCostcenterNavigation { get; set; }
        public virtual Department FkDepartmentNavigation { get; set; }
        public virtual Jobtitle FkJobtitleNavigation { get; set; }
        public virtual Language FkLanguageNavigation { get; set; }
        public virtual Location FkLocationNavigation { get; set; }
    }
}

当然还有脚手架 DbContext(摘录):

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace UserManagement.Models
{
    public partial class UserManagementContext : DbContext
    {
        public UserManagementContext()
        {
        }

        public UserManagementContext(DbContextOptions<UserManagementContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Approver> Approver { get; set; }
        public virtual DbSet<Branche> Branche { get; set; }
        public virtual DbSet<CostCenter> CostCenter { get; set; }
        public virtual DbSet<DealerCompany> DealerCompany { get; set; }
        public virtual DbSet<Department> Department { get; set; }
        public virtual DbSet<Jobtitle> Jobtitle { get; set; }
        public virtual DbSet<Language> Language { get; set; }
        public virtual DbSet<Location> Location { get; set; }
        public virtual DbSet<Request> Request { get; set; }
        public virtual DbSet<RequestTypes> RequestTypes { get; set; }
        public virtual DbSet<SystemRole> SystemRole { get; set; }
        public virtual DbSet<SystemType> SystemType { get; set; }
        public virtual DbSet<Systems> Systems { get; set; }
        public virtual DbSet<Users> Users { get; set; }
        public virtual DbSet<Workplace> Workplace { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
.....

在我的启动过程中,我必须使用 services.AddTransient 而不是 AddSingleton 来加载 UserService,因为后者会 运行 出现以下错误:

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: UserManagement.Data.UserService Lifetime: Singleton ImplementationType: UserManagement.Data.UserService': Unable to resolve service for type 'UserManagement.Models.UserManagementContext' while attempting to activate 'UserManagement.Data.UserService'.)'

渲染组件时,它会尝试在执行 OnInitializedAsync() 之前创建视图。 它为您提供 null ref exc,因为它尝试呈现页面,并且对于每个调用数组迭代器的 NextItem() 但数组为空。

index.razor中的解决方案初始化ctor中的数组或将声明更改为: Users[] users = new Users[x]; 其中 x 是您要存储在列表中的元素数。 对于灵活的解决方案,我推荐使用 List 而不是数组。 List<User> users = new List<User>();

在调用 OnInitialized 之前已经构建了渲染树,foreach 将在 users 仍然是 null 的时间执行。您可以先分配 users 和空数组,或者 my 首选变体,使用 if 检查是否应该尝试呈现用户。模板项目(有天气预报的)也是这样做的。

@page "/"
@using Models
@using Data
@inject UserService us

<form method="post">
    <input asp-page="/Create" type="button" value="Neuen Benutzer erstellen" />
</form>

@if (users == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <form method="post">
        <table class="table">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>UserID</th>
                    <th>Name</th>
                    <th>Supervisor</th>
                    <th>Ersteller</th>
                    <th>Erstelldatum</th>
                    <th>Optionen</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var user in users)
                {
                    <tr>
                        <td>@user.PkId</td>
                        <td>@user.UserId</td>
                        <td>@user.FirstName @user.LastName</td>
                        <td>@user.Supervisor</td>
                        <td>@user.CreationUser</td>
                        <td>@user.CreationDate</td>
                        <td>
                            <a>Delete Account</a><br />
                            <a asp-page="/Edit"> Edit Account</a>
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    </form>
}

@code 
{
    Users[] users;

    protected override async Task OnInitializedAsync()
    {
        users = await us.GetUsersAsync();
    }
}

问题出在下面的代码行中:

 u = await _context.Users.ToArrayAsync();

当你在上面的代码中使用await时,GetUsersAsync方法会被挂起,直到等待的任务完成,然后OnInitializedAsync方法也会被挂起。所以当Users数组为null时一个组件被渲染

把上面的代码改成

 u = _context.Users.ToArray();