如何在.NET EF Core开发的API中获取指定Diet对应的Recipe列表
问题根源
你遇到的两个核心错误原因如下:
- 路由配置缺失:你的Action标注了
[FromRoute] int DietId但路由模板没有对应的{DietId}占位符,导致接口无法从路由中拿到传入的DietId,参数默认值为0,自然筛选不到对应的Diet,返回空列表。 - 类型转换非法:你通过Select创建的是匿名类型对象,既不是Diet实体也不是Recipe实体,强转不符合.NET类型系统规则,直接抛出类型转换异常。
解决方案
方案1:直接返回Recipe实体列表
如果允许直接返回Recipe实体,直接用SelectMany压平关联的Recipes集合即可:
[HttpGet("[action]/{DietId}")] // 补全路由占位符,才能正常读取路由中的DietId public async Task<IEnumerable<Recipe>> GetRecipesFromDiet([FromRoute] int DietId) { return await _context.Diets .Where(d => d.DietId == DietId) .SelectMany(d => d.Recipes) // 把每个Diet对应的Recipes集合压平为Recipe序列 .AsNoTracking() .ToListAsync(); }
注:EF Core 3.0及以上版本的投影查询会自动处理关联加载,不需要手动加
Include也能正常获取关联数据。
方案2:返回自定义DTO(仅返回需要的字段)
如果不需要返回Recipe实体的全部字段,建议先定义DTO类,再做投影:
- 首先定义Recipe传输对象:
public class RecipeDto { public int RecipeId { get; set; } public string Name { get; set; } public string Description { get; set; } public string Preparation { get; set; } public string Ingredients { get; set; } }
- 修改Action代码:
[HttpGet("[action]/{DietId}")] public async Task<IEnumerable<RecipeDto>> GetRecipesFromDiet([FromRoute] int DietId) { return await _context.Diets .Where(d => d.DietId == DietId) .SelectMany(d => d.Recipes.Select(r => new RecipeDto { RecipeId = r.RecipeId, Name = r.Name, Description = r.Description, Preparation = r.Preparation, Ingredients = r.Ingredients })) .AsNoTracking() .ToListAsync(); }
内容的提问来源于stack exchange,提问作者DarkMage
相关产品推荐
相关产品推荐

