ASP.NetコアWeb APIの実装方法と更新メソッドの正しい呼び出し方法

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

質問

私は次のようにお互いに関連する2つのモデルを持っています:

 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 

間違った要求を送信していますか、コントローラまたはリポジトリのいずれかでメソッドを正しく実装していませんか? 1回のリクエストで親エンティティまたは子エンティティを部分的に更新できないのはなぜですか?

人気のある回答

データモデルをAPIとして直接公開し、特にデータバインディングをモデルバインディングを使用してアクションのパラメータとして直接受け入れることは好ましくありません。代わりに、クライアントに表示しているものだけを含むViewModelクラスを使用するか、クライアントの更新を許可しているViewModelクラスを使用します。多くの場合、このモデルを平坦化して、他のオブジェクトを含むオブジェクトを持たないようにします(現在のように)。

モデルの両方向にナビゲーションプロパティがある場合は、問題が発生する可能性があります。これにより、オブジェクトのシリアル化が難しくなり、EFが変更を追跡するのが難しくなる可能性があります。私は、親オブジェクトにその子にナビゲーションプロパティを持たせる傾向がありますが、子は親に戻る外部キー参照(intまたはguidプロパティ)しか持たないのです。あなたのケースでは、これはBenefitから仮想CoreGoalプロパティを削除することを意味します。

BenefitクラスのCoreGoalIDプロパティにタイプミスがあり、CoreGoalDであるため、問題が発生することもあります。

これらのいずれかがあなたの特定の問題を解決するかどうかを教えてください。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ