.NET 6 Web API问题:访问product.Category.Name时Category为Null
问题排查与解决方案
核心原因分析
- EF Core关联数据未加载:仓储层仅返回
Products的IQueryable,未主动加载关联的Category。EF Core默认延迟加载,但如果上下文在序列化时已释放,或延迟加载未开启,就会导致Category为null。 - DTO映射缺失:当前
ProductDto未包含Category相关字段,即便EF加载了Category,AutoMapper也不会自动将这部分数据映射到DTO中。
解决方案步骤
步骤1:确保关联数据被加载
有两种方式可以加载关联的Category:
方式一:使用Include主动加载(推荐,按需加载场景)
修改仓储层的GetProducts方法,显式关联加载Category:
public IQueryable<Product> GetProducts() { return _context.Products .Include(p => p.Category) // 加载关联的Category实体 .OrderBy(x => x.Name); }
方式二:开启延迟加载(全局需要关联数据的场景)
如果需要全局启用延迟加载,需满足两个条件:
- 实体的导航属性已标记为
virtual(你的代码已满足) - 在DbContext配置中开启延迟加载代理:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer("你的数据库连接字符串") .UseLazyLoadingProxies(); // 启用延迟加载 }
注意:延迟加载要求上下文在序列化时保持活跃,否则仍会出现null,比如控制器直接返回IQueryable时,序列化可能在上下文释放后执行。
步骤2:更新DTO并配置AutoMapper映射
先修改ProductDto,添加Category相关字段:
public class ProductDto { public int Id { get; set; } public string Name { get; set; } = null!; public string Description { get; set; } = null!; public int CategoryId { get; set; } public double Price { get; set; } public string PhotoUrl { get; set; } = null!; // 添加CategoryDto字段 public CategoryDto Category { get; set; } = null!; }
然后配置AutoMapper的映射规则,确保实体到DTO的关联映射生效:
public class MappingProfile : Profile { public MappingProfile() { CreateMap<Category, CategoryDto>(); CreateMap<Product, ProductDto>(); } }
步骤3:修改控制器,返回DTO而非实体
直接返回实体IQueryable容易引发序列化问题,建议映射为DTO后返回:
[HttpGet] public ActionResult<IEnumerable<ProductDto>> GetProducts() { var products = _productRepository.GetProducts(); if (!products.Any()) { return NotFound(); } var productDtos = _mapper.Map<IEnumerable<ProductDto>>(products); return Ok(productDtos); }
额外检查:SeedData需包含Category数据
你的SeedData仅添加了Product,需确保Category也被正确初始化:
modelBuilder.Entity<Category>(entity => { entity.HasData( new Category { Id = 1, Name = "分类1" }, new Category { Id = 2, Name = "分类2" } ); }); modelBuilder.Entity<Product>(entity => { entity.HasData( new Product { Id = 1, Name = "Hello", Description = "1", PhotoUrl = "111", Price = 10, CategoryId = 1 }, new Product { Id = 2, Name = "World", Description = "2", PhotoUrl = "111", Price = 20, CategoryId = 2 } ); });
内容的提问来源于stack exchange,提问作者Opal David
相关产品推荐
相关产品推荐

