联接两个表在 Razor 页面上不起作用

Join of Two Tables Not Working on Razor Page

提问人:MelB 提问时间:9/15/2023 最后编辑:Md Farid Uddin KironMelB 更新时间:9/15/2023 访问量:44

问:

我尝试在 Razor 页面应用上创建一个报表页,但无法使其正常工作。我有一个类似的工作应用程序,看不到我在哪里做任何不同的事情,但一定遗漏了一些明显的东西。

以下是有问题的观点:

@page
@model RabiesShotTracker.Pages.Reports.UnpaidBills.IndexModel

<div id="UnpaidBillsIndex" class="container p-3">
    <div class="row pt-4">
        <div class="col-6">
            <h2 class="text-primary">Unpaid Bills</h2>
        </div>
    </div>

    <br /><br />

    <form asp-page="./Index" method="post">
        <div id="UnpaidBillsReport" class="row pt-4">
            <div class="col-25">
                <h2 class="text-primary" align="center">Public Health</h2>
                <h3 class="text-primary" align="center">Rabies Shots Unpaid Bills</h3>
            </div>
                <table id="DataTable" class="table table-bordered" style="width:75%" align="center">
                    <thead>
                        <tr>
                            <th style ="text-align: center">
                                Incident No
                            </th>
                            <th style="text-align: center">
                                Patient Name
                            </th>
                            <th style="text-align: center">
                                Date of Birth
                            </th>
                            <th style="text-align: center">
                                Exposure Date
                            </th>
                            <th style="text-align: center">
                                Date Shot Scheduled
                            </th>
                            <th style="text-align: center">
                                Date Shot Received
                            </th>
                        </tr>
                    </thead>
                    <tbody>

                        @for (var i = 0; i < Model.Client.Shots.Count; i++)
                        {
                            <tr>
                                <td style="width: 15%">
                                    <div class="mb-3">
                                        <input asp-for="Client.Shots[i].IncidentNo" type="text" readonly class="form-control-plaintext" />
                                    </div>
                                </td>
                                <td style="width: 25%">
                                    <div class="mb-3">
                                        <input asp-for="Client.FullName" type="text" readonly class="form-control-plaintext" />
                                    </div>
                                </td>
                                <td style="width: 15%">
                                    <div class="mb-3">
                                        <input asp-for="Client.Birthdate" type="text" readonly class="form-control-plaintext" />
                                    </div>
                                </td>
                                <td style="width: 15%">
                                    <div class="mb-3">
                                        <input asp-for="Client.ExposureDate" type="text" readonly class="form-control-plaintext" />
                                    </div>
                                </td>
                                <td style="width: 15%">
                                    <div class="mb-3">
                                        <input asp-for="Client.Shots[i].ShotSchedDate" type="text" readonly class="form-control-plaintext" />
                                    </div>
                                </td>
                                <td style="width: 15%">
                                    <div class="mb-3">
                                        <input asp-for="Client.Shots[i].ShotRecdDate" type="text" readonly class="form-control-plaintext" />
                                    </div>
                                </td>
                            </tr>
                        }
                    </tbody>
                </table>
    </form>
</div>

这是它背后的.cs:

using RabiesShotTracker.Data;
using RabiesShotTracker.Model;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace RabiesShotTracker.Pages.Reports.UnpaidBills
{
    public class IndexModel : PageModel
    {
        private readonly ApplicationDbContext _db;

        public Client Client { get; set; }
        public Shot Shot { get; set; }


        public IndexModel(ApplicationDbContext db)
        {
            _db = db;
        }

        public void OnGet(int Id)
        {
            Client = _db.Client
                    .Include(client => client.Shots).FirstOrDefault(client => client.ClientId == Id);
        }

    }
}

以下是客户端模型的相关部分:

using System.ComponentModel.DataAnnotations;

namespace RabiesShotTracker.Model
{
    public class Client
    {
        [Key]
        [Display(Name = "Client Id")]
        public int ClientId { get; set; }

        public List<Shot>? Shots { get; set; }

        [Required]
        [Display(Name = "Client No (###)")]
        public string? ClientNo { get; set; }

        [Required]
        [Display(Name = "Incident No")]
        public string? IncidentNo { get; set; }

以下是 Shot 模型的相关部分:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RabiesShotTracker.Model
{
    public class Shot
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public int ShotId { get; set; }

        [Required]
        public int ClientId { get; set; }

        public Client? Client { get; set; }

        [Required]
        [Display(Name = "Incident No")]
        public string? IncidentNo { get; set; }
        
        [Required]
        [Display(Name = "Client No")]
        public string? ClientNo { get; set; }

当我运行应用程序时,我收到一个 NullReferenceException:对象引用未设置为对象的实例。在生产线上:

@for (var i = 0; i < Model.Client.Shots.Count; i++)

两个表(Client 和 Shot)都有值,所以我不确定我做错了什么?我是否错过了一些明显的东西?

提前感谢您提供的任何帮助。我盯着这个看太久了。

C# ASP.NET 实体框架核心 razor-pages nullreferenceexception

评论

0赞 topsail 9/15/2023
当你在 OnGet() 方法上放置断点时,你有镜头吗?
0赞 MelB 9/15/2023
如果我做对了,Client 和 Shot 都返回 null。
0赞 topsail 9/15/2023
所以你可能不应该得到 null ...您如何传入“客户端”的 ID?
0赞 Md Farid Uddin Kiron 9/15/2023
你能分享一下你的外表吗?您是否签入了数据库,是否已在表列中生成了外键?此外,您是否尝试过在 clientId 属性上添加外键引用?ApplicationDbContext

答:

1赞 Md Farid Uddin Kiron 9/15/2023 #1

两个表(Client 和 Shot)都有值,所以我不确定 我做错了什么?我是否错过了一些明显的东西?

首先,您的 Shot 表设计或模型定义违反了 3NF 数据库规范化,因为通过客户端 ID,您可以访问镜头表中的所有实体,因此,IncidentNo 和 ClientNo 只是 Client 表的重复。

但是,表关系应该不存在通过使用 ClientId 联接来获取数据的问题。我已经与您的代码片段一起进行了调查,并尝试插入一些手动数据,它似乎按预期工作。

什么,我假设请检查您的搜索键,即您在方法中传递的 ID。OnGet(int Id)

除此之外,您还应该检查您的 ApplicationDbContext 定义,以及它是否相应地创建了您的数据库表架构。

最重要的是,请检查您的 ClientId 是否在 Shot 表上有正确的处理。

我已经尝试了与您相同的方式,并且我已经执行了迁移命令,并且它已创建数据库表,如下所示:

迁移后的数据库表:

enter image description here

Appsetting.json:

"ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\ProjectModels;Database=RazorPageTableJoinDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

Db 上下文类:

public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

        public DbSet<Client> Clients { get; set; }
        public DbSet<Shot> Shots { get; set; }


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            

        }
    }

Program.cs 类:

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(x => x.UseSqlServer(connectionString));

// Add services to the container.
builder.Services.AddRazorPages();

剃刀页面 .cs:

public class ForeignKeyTableJoinModel : PageModel
    {
        private readonly ApplicationDbContext _db;

        public Client Client { get; set; }
        public Shot Shot { get; set; }


        public ForeignKeyTableJoinModel(ApplicationDbContext db)
        {
            _db = db;
        }

        public void OnGet()
        {
            var Id = 1;
            
            Client = _db.Clients
                    .Include(client => client.Shots).FirstOrDefault(client => client.ClientId == Id);
        }
    }

输出:

enter image description here

enter image description here

注意:确保给定的 ClientId 具有正确的数据,并且在数据库表中它们具有正确的关系。此外,还要将查询发送到 appsetting.json 连接字符串中的正确数据库。

评论

0赞 MelB 9/16/2023
当我在公共无效 OnGet(int Id) 中取出“int Id”并像您一样添加 var = 1 时,报告将起作用。如果我将其改回 public void OnGet(int Id),运行报告会给我 null 异常错误。App Db Context 很好。但是,数据库表中缺少 FK。通过镜头模型添加它的正确语法是什么?我一定是弄错了。我正在尝试[ForeignKey(“Client.ClientId”)]。
0赞 Md Farid Uddin Kiron 9/18/2023
是的,如果您想在加载客户端和插槽列表的视图时进行过滤,您应该得到 null 引用异常,因为在加载时您将没有任何特定的 ID,而是完整的列表,并且此参数将始终为 null onload。必须从视图发送特定 ID 才能筛选 razor.cs 文件中的查询。OnGet(int Id)OnGet(int Id)
0赞 MelB 9/18/2023
啊,好吧。谢谢。在这种特殊情况下,我正在寻找的是所有没有为他们的镜头付费的客户。有问题的字段位于 Shot 模型中:Shot.ShotPaidDate。我将如何更改我的对账单以寻找所有没有带薪日期的客户?我只是不确定语法。
0赞 MelB 9/19/2023
我在报表上需要的项目来自客户端模型和镜头模型。
0赞 Md Farid Uddin Kiron 9/19/2023
您所需要的只是一个搜索框,从中获取值,或者它可以是基于您的搜索条件的下拉列表,获取输入并再次填充视图。在这个问题上,我们实际上弄清楚了为什么你不工作。所以,如果你能为此发布新问题,那就太好了,这样这个问题就会保持特定的问题导向,如果我根据你当前的要求更新了这个问题,这个答案会很长。"Join of Two Tables Not Working on Razor Page"