我有两个相互关联的模型如下:
public class CoreGoal
{
[Key]
public long CoreGoalId { get; set; }
[Required]
public string Title { get; set; }
public virtual ICollection<Benefit> Benefits { get; set; }
public CoreGoal()
{
}
}
并且
public class Benefit
{
[Key]
public long BenefitId { get; set; }
[Required]
public string What { get; set; }
public long CoreGoalD { get; set; }
[ForeignKey("CoreGoalId")]
public virtual CoreGoal CoreGoal { get; set; }
public Benefit()
{
}
}
来自控制器类的我的UPDATE方法:
[Route("api/[controller]")]
public class CoreGoalController : Controller
{
private readonly ICoreGoalRepository _coreGoalRepository;
//Controller
public CoreGoalController(ICoreGoalRepository coreGoalRepository) {
_coreGoalRepository = coreGoalRepository;
}
...
//Update
[HttpPut("{id}")]
public IActionResult Update(long id, [FromBody] CoreGoal item)
{
if (item == null || item.CoreGoalId != id)
{
return BadRequest();
}
var coreGoal = _coreGoalRepository.Find(id);
if (coreGoal == null)
{
return NotFound();
}
coreGoal.Title = item.Title;
coreGoal.Benefits = item.Benefits;
_coreGoalRepository.UpdateCoreGoal(coreGoal);
return new NoContentResult();
}
}
和我的存储库:
public class CoreGoalRepository : ICoreGoalRepository
{
private readonly WebAPIDataContext _db;
public CoreGoalRepository(WebAPIDataContext db)
{
_db = db;
}
...
//Find specific
public CoreGoal Find(long key)
{
return _db.CoreGoals.FirstOrDefault(t => t.CoreGoalId == key);
}
//Update specific
public void UpdateCoreGoal(CoreGoal coreGoal)
{
_db.CoreGoals.Update(coreGoal);
_db.SaveChanges();
}
}
我的问题是它是一种写UPDATE方法的正确方法吗? 考虑当我做GET请求时,我回来了:
[
{
"coreGoalId": 1,
"title": "Goal 1",
"benefits": [
{
"benefitId": 1,
"what": "Benefit 1",
"coreGoalD": 0
}
]
}
]
现在我想更新这个核心目标,所以我做了如下PUT请求:
它给了我
An exception of type 'Microsoft.EntityFrameworkCore.DbUpdateException' occurred in Microsoft.EntityFrameworkCore.dll but was not handled in user code
我发送了错误的请求,或者我在控制器或存储库中错误地实现了该方法?为什么我不能仅在一个请求中部分更新父实体或子实体?
答案 0 :(得分:0)
直接将您的数据模型公开为您的API是一个坏主意,尤其是通过模型绑定直接接受您的数据模型作为您的操作的参数。相反,请使用仅包含您向客户端显示的内容的ViewModel类,或者允许客户端更新的ViewModel类。在许多情况下,将此模型展平是有意义的,因此它不会包含包含其他对象的对象(就像您当前所做的那样)。
如果您的模型中的导航属性同时向两个方向发展,则可能会遇到问题。这会使序列化对象变得更加困难,并且可能使EF更难以跟踪更改。我倾向于让父对象具有其子对象的导航属性,但子对象只有外键引用(int或guid属性)回到它们的父对象。在您的情况下,这意味着从Benefit中删除虚拟CoreGoal属性。
您可能也遇到问题,因为您的Benefit类的CoreGoalID属性有拼写错误并且是CoreGoalD。
如果有任何问题可以解决您的具体问题,请告诉我。