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

.NET Core MVC 创建关联Product列表的Order实体空引用异常如何解决

问题原因及修正方案

项目结构

1 空引用异常直接原因

  • Order类的ProductList导航属性未做初始化,默认值为null,调用AddProducts方法时执行ProductList.ToList()会直接触发空引用异常
  • 循环中调用ProductList.ToList().Add(product)存在逻辑错误:ToList()每次都会生成一个全新的临时集合对象,Add操作是作用在这个临时集合上,执行完就被回收,根本不会把产品保存到Order的ProductList属性中,添加操作完全无效

2 实体设计存在的规范问题

2.1 导航属性类型错误

EF Core中用于增删操作的集合导航属性,不能用IEnumerable<T>类型,该类型只支持遍历,不支持原生的集合修改操作,应当改用ICollection<T>类型。

2.2 缺失无参构造函数

你的Product类只声明了带参数的构造函数,编译器不会自动生成默认无参构造函数,EF Core做数据库实体映射的时候需要无参构造函数来实例化对象,后续查询操作会直接报错。

2.3 多对多关系设计缺失

从业务逻辑来看,Order和Product属于多对多关系,你的现有设计没有中间表关联,也没有存储购买数量、下单时的产品快照价格的字段,不符合实际业务需求,后续会出现数据覆盖、无法统计购买数量等问题。

3 修正后的代码示例

修正后的Product类

using System.ComponentModel.DataAnnotations;

namespace Domain.Entities
{
    public class Product
    {
        [Key]
        public int ProductID { get; set; }
        [Required]
        public string ProductName { get; set; }
        [Required]
        public int ProductPrice { get; set; }

        // 补充EF Core需要的无参构造函数
        public Product()
        {
        }

        public Product(string productName, int productPrice)
        {
            ProductName = productName;
            ProductPrice = productPrice;
        }

        public void ApplyDiscounts(int discountValue) 
        {
            // 原逻辑判断写反,折扣大于等于产品价格时减完会出现负数,已修正
            if (discountValue <= this.ProductPrice) 
            {
                this.ProductPrice -= discountValue;
            }
        }
    }
}

修正后的Order类

using Domain.Entities;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace Project.Domain.Entities
{
    public class Order
    {
        [Key]
        public int OrderId { get; set; }
        // 改用ICollection,同时初始化属性避免空引用
        public virtual ICollection<Product> ProductList { get; private set; } = new List<Product>();

        public Order()
        {
        }

        public Order AddProducts(IEnumerable<Product> productListToAdd) 
        {
            // 直接添加到现有集合,无需每次生成临时List
            foreach (var product in productListToAdd) 
            {
                ProductList.Add(product);
            }
            return this;
        }
    }
}

4 业务优化建议

如果要符合实际生产业务,建议新增OrderItem中间表存储关联关系,示例结构如下:

public class OrderItem
{
    [Key]
    public int Id { get; set; }
    public int OrderId { get; set; }
    public int ProductId { get; set; }
    // 存储下单时的产品价格,避免后续产品改价导致订单数据错乱
    public int SnapshotPrice { get; set; }
    // 存储购买数量
    public int Quantity { get; set; }
    public virtual Order Order { get; set; }
    public virtual Product Product { get; set; }
}

之后把Order类中的ProductList改为ICollection<OrderItem> OrderItems即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 02:36:02