You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC创建Contract时出现NullReferenceException求助

解决ASP.NET Core MVC创建Contract时的NullReferenceException问题

问题说明

在ASP.NET Core MVC项目中创建新Contract时触发NullReferenceException,报错出现在模型的返回方法中。需求是基于CarGroup的PreisTag(日单价)结合租赁时长计算总价,让Contract模型返回该总价并显示在ContractsController的列表中。

异常原因分析

出现空引用的核心原因有三个:

  1. 导航属性未加载:EF Core默认使用延迟加载,当Contract的CarList、或CarList的CarGroup未被显式加载时,访问这些属性会返回null,触发异常。
  2. 循环引用导致的加载问题:Contract和CarList互相持有对方的引用,这种循环依赖会导致EF Core无法正确加载关联数据,也容易引发空引用。
  3. 未做null校验:在计算总价的方法中,直接访问Contract.AbgabeDatum、CarGroup.PreisTag等属性,没有先判断这些对象是否为null。

修复方案

1. 调整总价计算逻辑到Contract模型

租赁时长是Contract的属性(AusleihDatum和AbgabeDatum),总价作为Contract的衍生属性,直接在Contract中计算更合理,同时避免循环依赖。

2. 增加null校验

在计算前先检查必要的关联对象是否为空,避免空引用异常。

3. 查询时显式加载导航属性

在ContractsController的查询方法中,使用Include和ThenInclude显式加载所有需要的关联数据,不要依赖延迟加载。

4. 移除CarList中不必要的Contract关联

删除CarList里的Contract相关属性,消除循环引用。

修改后的代码示例

Contract模型修改

public class Contract 
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public Customer Customer { get; set; }
    public int CarListId{get;set;}
    public CarList CarList { get; set; }
    
    [DataType(DataType.Date)]
    public DateTime AusleihDatum{ get; set; }

    [DataType(DataType.Date)]
    public DateTime AbgabeDatum { get; set; }
    
    public int KilometerstandAnfang { get; set; }
    public int KilometerstandEnde { get; set; }

    public double GesamtPreis
    {
        get
        {
            // 校验必要对象是否为空
            if (CarList == null || CarList.CarGroup == null)
                return 0; // 可根据需求改为抛出明确异常,比如throw new InvalidOperationException("关联数据未加载");
            
            if (AbgabeDatum < AusleihDatum)
                throw new InvalidOperationException("归还日期早于租赁日期");
                
            TimeSpan differenz = AbgabeDatum - AusleihDatum;
            int ausleihzeit = (int)differenz.TotalDays;
            // 确保至少按1天计算(当天归还的情况)
            ausleihzeit = Math.Max(ausleihzeit, 1);
            
            return ausleihzeit * CarList.CarGroup.PreisTag;
        }
    }
}

CarList模型修改

namespace MvcCar2.Models
{
    public class CarList
    {
        public int Id { get; set; }

        public string Hersteller { get; set; }
        public string Modell { get; set; }
        public string Kennzeichen { get; set; }
        public string Farbe { get; set; }

        public int Kilometerstand { get; set; }

        public int CarGroupId { get; set; }
        public CarGroup CarGroup { get; set; }
        
        // 移除不必要的Contract关联,消除循环引用
        // [NotMapped]
        // public int ContractId { get; set; }
        // public Contract Contract { get; set; }
        
        // 移除原GesamtPreis方法,计算逻辑已移至Contract
    }
}

ContractsController查询方法修改

在获取Contract列表时,显式加载关联的CarList和CarGroup:

public async Task<IActionResult> Index()
{
    var contracts = _context.Contracts
        .Include(c => c.Customer)
        .Include(c => c.CarList)
            .ThenInclude(cl => cl.CarGroup) // 链式加载CarList的CarGroup
        .ToListAsync();
        
    return View(await contracts);
}

额外注意事项

  • 创建Contract时,确保传入的CarListId对应的CarList在数据库中存在,否则CarList属性会为null。
  • 如果使用延迟加载,需确保DbContext在访问导航属性时仍处于激活状态,但显式加载更可靠,避免上下文释放后引发的空引用。

内容的提问来源于stack exchange,提问作者Miki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 19:27:03