ASP.Net核心web api正確實現/調用更新方法的方法

asp.net-core asp.net-core-mvc entity-framework-core

我有兩個相互關聯的模型如下:

 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 

我發送了錯誤的請求,或者我在控制器或存儲庫中錯誤地實現了該方法?為什麼我不能僅在一個請求中部分更新父實體或子實體?

熱門答案

直接將您的數據模型公開為您的API是一個壞主意,尤其是通過模型綁定直接接受您的數據模型作為您的操作的參數。相反,請使用僅包含您向客戶端顯示的內容的ViewModel類,或者允許客戶端更新的ViewModel類。在許多情況下,展平此模型是有意義的,因此它沒有包含其他對象的對象(就像您當前所做的那樣)。

如果您的模型中的兩個方向都有導航屬性,則可能會遇到問題。這會使序列化對像變得更加困難,並且可能使EF更難以跟踪更改。我傾向於讓父對象具有其子對象的導航屬性,但子對像只有外鍵引用(int或guid屬性)回到它們的父對象。在您的情況下,這意味著從Benefit中刪除虛擬CoreGoal屬性。

您可能也遇到問題,因為您的Benefit類的CoreGoalID屬性有拼寫錯誤並且是CoreGoalD。

如果其中任何一個解決您的具體問題,請告訴我。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow