如何高效填充.NET Core API中实体的导航属性?
高效填充Customer导航属性City的方法
问题背景
我有一个从前端提交至.NET Core API的复合模型,当前使用DbSet<T>.Find(id)方法为Customer.City属性赋值。请问是否存在更高效的方式,从数据库关联数据中填充City这一导航属性?
相关代码定义
CustomerDto
public class CustomerDto { public int CustomerId { get; set; } public string Code { get; set; } public string DisplayName { get; set; } public int CityId { get; set; } }
DbContext中的Customer实体
public class Customer : ISystemOperated, ICachable { public int CustomerId { get; set; } public string? Code { get; set; } public string DisplayName { get; set; } public virtual City? City { get; set; } }
AutoMapper映射配置
CreateMap<CustomerDto, Customer>();
高效解决方案
1. 创建Stub实体直接关联(最优性能)
不需要查询完整的City实体,只需要创建一个仅包含主键的"Stub"实体,EF Core的追踪机制会自动处理关联,完全避免数据库查询:
var customer = mapper.Map<Customer>(customerDto); // 仅需设置CityId,EF会自动识别关联 customer.City = new City { CityId = customerDto.CityId }; dbContext.Customers.Update(customer); await dbContext.SaveChangesAsync();
2. 让AutoMapper自动生成Stub实体
把关联逻辑整合到AutoMapper配置中,映射时自动完成City的关联设置,省去手动赋值步骤:
CreateMap<CustomerDto, Customer>() .ForMember(dest => dest.City, opt => opt.MapFrom(src => new City { CityId = src.CityId }));
之后直接映射即可:
var customer = mapper.Map<Customer>(customerDto); dbContext.Customers.Update(customer); await dbContext.SaveChangesAsync();
3. 批量场景下的批量查询关联
如果需要处理多个CustomerDto,把所有需要的CityId收集起来,一次性查询所有City实体,再逐一关联,减少数据库查询次数:
// 提取所有不重复的CityId var cityIds = customerDtos.Select(d => d.CityId).Distinct().ToList(); // 批量查询所需City var cities = await dbContext.Cities.Where(c => cityIds.Contains(c.CityId)).ToListAsync(); // 映射并关联 var customers = mapper.Map<List<Customer>>(customerDtos); foreach (var (customer, dto) in customers.Zip(customerDtos)) { customer.City = cities.FirstOrDefault(c => c.CityId == dto.CityId); }
总结
- 单条数据处理优先用方法1或2,零数据库查询,性能最优;
- 批量数据处理用方法3,将多次查询合并为一次,提升批量操作效率。
内容的提问来源于stack exchange,提问作者LojiSmith
相关产品推荐
相关产品推荐

