【问题标题】:ASP.Net core web api correct way of implementing/calling update methodASP.Net core web api正确的实现方式/调用更新方法
【发布时间】:2017-03-24 09:07:17
【问题描述】:

我有两个相互关联的模型如下:

 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 

我是否发送了错误的请求,或者我在控制器或存储库中错误地实现了该方法?为什么我不能在一个请求中只更新部分父实体或子实体?

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc entity-framework-core


    【解决方案1】:

    将数据模型直接公开为 API 是个坏主意,尤其是通过模型绑定直接接受数据模型作为操作的参数。相反,请使用仅包含您向客户端显示或允许客户端更新的内容的 ViewModel 类。在许多情况下,扁平化这个模型是有意义的,这样它就不会包含包含其他对象的对象(就像你目前的那样)。

    如果您的模型中也有双向导航属性,您可能会遇到问题。这会使序列化对象变得更加困难,并且会使 EF 更难跟踪更改。我倾向于让父对象对其子对象具有导航属性,但子对象只有对其父对象的外键引用(int 或 guid 属性)。在您的情况下,这意味着从 Benefit 中删除虚拟 CoreGoal 属性。

    您可能还会遇到问题,因为您的 Benefit 类的 CoreGoalID 属性有错字并且是 CoreGoalD。

    让我知道这些是否能解决您的具体问题。

    【讨论】:

    • 这是我使用 ASP.Net 核心的时间,所以我基本上是在遵循文档。我有几个问题: 1. 我正在构建 Web API,在这种情况下 ViewModel 是否有意义,或者它是否与 MVC 相关(因为他们在文档中没有提到)? 2.如果是Web API,这样的导航属性(Context in Benefit)是不是必须的,它们到底起什么作用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-23
    • 2015-11-01
    • 2021-12-28
    • 2021-05-17
    • 2021-10-13
    • 2022-11-04
    • 2016-10-12
    相关资源
    最近更新 更多