繁体   English   中英

如何使用 EF Core 3.1.5 解决 ASP.net Core 应用程序中的 null 引用异常?

[英]How can I resolve null reference exception in ASP.net Core application using EF Core 3.1.5?

当我将以下内容添加到客户端详细信息视图时,我收到了 null 引用异常:

<dt>
    @Html.DisplayNameFor(model => model.Contacts)
</dt>
<dd>
    <table class="table">
        <tr>
            <th>FN</th>
            <th>LN</th>
            <th>Email</th>
            <th>Contact Type</th>
        </tr>
        @foreach (var item in Model.Contacts)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.FN)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.LN)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Email)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ContactType)
                </td>
            </tr>
        }
    </table>
</dd>

为什么我在@Html.DisplayNameFor(model => model.Contacts)处收到 null 参考异常,我该如何解决?

以下是Client class 删除了数据注释以便于阅读:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace scms_core.Models
{
    public class Client
    {        
        public int Id { get; set; }
        public string CrtdBy { get; set; }        
        public DateTime CrtdDt { get; set; }
        public string FN { get; set; }
        public string LN { get; set; }
        public string BN { get; set; }

        public int ClientTypeId { get; set; }
        public tlClientType ClientType { get; set; }

        public virtual ICollection<Contact> Contacts { get; set; }
    }
}

以下是Contact class,也去掉了数据注释以便于阅读:

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

namespace scms_core.Models
{
    public class Contact
    {
        public int Id { get; set; }
        public string CrtdBy { get; set; }
        public DateTime CrtdDt { get; set; }
        public string FN { get; set; }
        public string LN { get; set; }
        public string Email { get; set; }

        public int ContactTypeId { get; set; }
        public tlContactType ContactType { get; set; }

        public int ClientId { get; set; }
        public virtual Client Client { get; set; }
    }
}

当我删除应该获取联系信息的代码的引用时,详细信息页面将起作用。 当我将此代码添加到视图时,它只是失败了。 以下是客户详细信息视图:

@model scms_core.Models.Client

@{
    ViewData["Title"] = "Details";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Details</h1>

<div>
    <h4>Client</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.CrtdBy)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.CrtdBy)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.CrtdDt)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.CrtdDt)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.FN)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.FN)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.LN)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.LN)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.BN)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.BN)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.ClientType)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.ClientType.ClientType)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Contacts)
        </dt>
        <dd>
            <table class="table">
                <tr>
                    <th>FN</th>
                    <th>LN</th>
                    <th>Email</th>
                    <th>Contact Type</th>
                </tr>
                @foreach (var item in Model.Contacts)
                {
                    <tr>
                        <td>
                            @Html.DisplayFor(modelItem => item.FN)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.LN)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.Email)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.ContactType)
                        </td>
                    </tr>
                }
            </table>
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
    <a asp-action="Index">Back to List</a>
</div>

下面是 controller 代码:

public async Task<IActionResult> Details(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var client = await _context.Clients
            .Include(c => c.ClientType)
            .FirstOrDefaultAsync(m => m.Id == id);

        if (client == null)
        {
            return NotFound();
        }

        return View(client);
    }

您应该像这样在客户端 model 构造函数中初始化联系人集合

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace scms_core.Models
{
  public class Client
  {        
    public Client()
    {
       Contacts = new HashSet<Contact>();
    }

    public int Id { get; set; }
    public string CrtdBy { get; set; }        
    public DateTime CrtdDt { get; set; }
    public string FN { get; set; }
    public string LN { get; set; }
    public string BN { get; set; }

    public int ClientTypeId { get; set; }
    public tlClientType ClientType { get; set; }

    public virtual ICollection<Contact> Contacts { get; set; }
}

}

应该是这样,将Id更改为ClientID并制作一个[Key][Table]您想要拥有主键并制作表格的地方:

[Table("Client")]
public class Client
    {        
        [Key]
        public int ClientID { get; set; }
        public string CrtdBy { get; set; }        
        public DateTime CrtdDt { get; set; }
        public string FN { get; set; }
        public string LN { get; set; }
        public string BN { get; set; }    
        public int ClientTypeID { get; set; }
        [ForeignKey("ClientTypeID")]
        public ClientType ClientType { get; set; }
        public int ContactID { get; set; }
        [ForeignKey("ContactID")]
        public virtual Contact Contact { get; set; }   

        public ICollection<Contact> Contacts { get; set; }
    }

Id更改为ContactID

[Table("Contact")]
public class Contact
    {
        [Key]
        public int ContactID { get; set; }
        public string CrtdBy { get; set; }
        public DateTime CrtdDt { get; set; }
        public string FN { get; set; }
        public string LN { get; set; }
        public string Email { get; set; }
        public int ContactTypeID { get; set; }
        [ForeignKey("ContactTypeID")]
        public virtual ContactType ContactType { get; set; }
        public int ClientID { get; set; }
        [ForeignKey("ClientID")]
        public virtual Client Client { get; set; }
    }

您的 controller 应该声明一个列表并将视图 model 发送到 razor 页面。 应该看起来像这样:

public async Task<ActionResult> Contacts()
    {
        var allClients = await _context.Clients.ToList();

        List<Contact> viewModel = allClients.Select(x => new Contacts
        {
            FN = x.FN,
            LN = x.LN,
            Email = x.Email,
            ContactType = x.ContactType
        }).ToList();


        return View(viewModel);
    }

您应该对将要创建数据库的所有模型执行相同的操作。 在您的联系人页面中,您没有提及您正在使用哪个@model ,但它应该看起来像这样: @model List<YourProject.UI.Models.Contacts>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM