如何在POST请求中使用Entity Framework自动生成的实体类型?
首先得明确你遇到的核心问题:不是[BindNever]的作用没生效,而是JSON里传递的CharacteristicId和CommodityId是字符串类型(比如"test1"),但你的CommoditiesCharacteristics类里这两个属性是int类型,模型绑定阶段无法完成字符串到整数的转换,才导致的执行失败。[BindNever]是告诉模型绑定器跳过某些属性的绑定,但你JSON里根本没传Id、Characteristic、Commodity这些属性,所以加这个特性完全没触及问题根源。
接下来给你两种可行的解决思路,你可以根据场景选择:
思路1:调整JSON数据格式(最简单,若能控制输入源)
如果JSON的生成方可以修改,直接把CharacteristicId和CommodityId的值改成合法的整数,比如:
{"Type":{"CharacteristicId":1,"CommodityId":2},...}
这样模型绑定就能顺利把JSON值映射到int类型属性上,不需要修改任何后端代码。
思路2:用DTO(数据传输对象)接收请求(推荐,符合最佳实践)
如果无法修改JSON的输入格式,最规范的做法是新建一个专门用于接收请求的DTO类,和你的EF实体类解耦,避免污染数据库实体。
步骤1:定义DTO类
// 单个钻头特征的DTO public class DrillCharacteristicDto { public string CharacteristicId { get; set; } public string CommodityId { get; set; } } // 整个钻头请求的DTO public class DrillRequestDto { public DrillCharacteristicDto Type { get; set; } public DrillCharacteristicDto ShankType { get; set; } public DrillCharacteristicDto SharpeningAngel { get; set; } public DrillCharacteristicDto SharpeningDirection { get; set; } public DrillCharacteristicDto MaterialFor { get; set; } public DrillCharacteristicDto WorkingLength { get; set; } public DrillCharacteristicDto Length { get; set; } public DrillCharacteristicDto Diameter { get; set; } }
步骤2:修改控制器方法接收DTO并映射到实体
[HttpPost] [Route("SaveDrill")] public IActionResult SaveDrill(DrillRequestDto drillDto) { // 先做数据验证:把字符串转成合法整数 if (!int.TryParse(drillDto.Type.CharacteristicId, out int charId) || !int.TryParse(drillDto.Type.CommodityId, out int commId)) { return BadRequest("CharacteristicId和CommodityId必须是合法的整数"); } // 将DTO转换为EF实体 var typeChar = new CommoditiesCharacteristics { CharacteristicId = charId, CommodityId = commId }; _toolStoreContext.CommoditiesCharacteristics.Add(typeChar); // 其他属性同理完成转换与添加 // ... _toolStoreContext.SaveChanges(); return Ok(); }
这种方式的好处是:实体类只负责数据库映射,DTO负责接收外部请求,两者职责清晰,后续不管是请求格式变化还是数据库结构调整,都不会互相影响。
不推荐的思路:修改实体类添加辅助属性
如果你不想新建DTO,也可以在CommoditiesCharacteristics里添加字符串类型的辅助属性,用[NotMapped]标记(告诉EF不要把这个属性映射到数据库列),再通过属性的get/set方法完成类型转换:
public partial class CommoditiesCharacteristics { public int Id { get; set; } public int CharacteristicId { get; set; } public int CommodityId { get; set; } public virtual DrillBitsCharacteristics Characteristic { get; set; } public virtual Commodities Commodity { get; set; } [NotMapped] [JsonPropertyName("CharacteristicId")] public string CharacteristicIdStr { get => CharacteristicId.ToString(); set => int.TryParse(value, out CharacteristicId); } [NotMapped] [JsonPropertyName("CommodityId")] public string CommodityIdStr { get => CommodityId.ToString(); set => int.TryParse(value, out CommodityId); } }
但这种做法会把请求处理的逻辑塞进数据库实体类里,违反了单一职责原则,后续维护起来会很麻烦,所以不建议使用。
内容的提问来源于stack exchange,提问作者A191919

