【问题标题】:REST API Best practice for handling junction dataREST API 处理联结数据的最佳实践
【发布时间】:2018-08-05 14:55:04
【问题描述】:

我正在研究面向服务的架构。我有 3 个表 Meeting、Stakeholder 和 MeetingStakeholder(一个联结表)。

所有 3 个表的 POCO 类的简单表示:

public class Meeting
{
    public int Id { get; set; }
    public IList<MeetingStakeholder> MeetingStakeholders { get; set; }
}

public class Stakeholder
{
    public int Id { get; set; }
}

public class MeetingStakeholder
{
    public int Id { get; set; }

    public int MeetingId { get; set; }
    public Meeting Meeting { get; set; }

    public int StakeholderId { get; set; }
    public Stakeholder Stakeholder { get; set; }
}

Meeting Dto 的简单表示:

public class MeetingDto
{
    public int Id { get; set; }
    public IList<int> StakeholderIds { get; set; }
}

在 PUT 动作中,

PUT: api/meetings/1

首先,我从 MeetingStakeholder(联结表)中删除所有现有记录,然后使用 meetingDto.StakeholderIds 准备新的 List&lt;MeetingStakeholder&gt; meetingStakeholders 并创建它。

{
   List<MeetingStakeholder> existingMeetingStakeholders = _unitOfWork.MeetingStakeholderRepository.Where(x=> x.MeetingId == meetingDto.Id);
   _unitOfWork.MeetingStakeholderRepository.RemoveRange(existingMeetingStakeholders);

   List<MeetingStakeholder> meetingStakeholders = ... ;

   _unitOfWork.MeetingRepository.Update(meeting);       
   _unitOfWork.MeetingStakeholderRepository.CreateRange(meetingStakeholders);
   _unitOfWork.SaveChanges();

   return OK(meetingDto);
}

对我来说一切都很好。但是我的建筑师告诉我,我做错了事。 他说,在 PUT 操作中(根据 SRP)我不应该删除和重新创建 MeetingStakeholder 记录,我应该只负责更新会议对象。

据他说,MeetingStakeholderIds(整数数组)应该在请求正文中发送到这些路由。

用于分配新的利益相关者参加会议。

POST:  api/meetings/1/stakeholders

从会议中删除现有的利益相关者。

Delete: api/meetings/1/stakeholders

但问题是,在会议编辑屏幕中,我的前端开发人员为利益相关者使用了多选。他需要维护两个整数数组。

最终用户从多选中取消选择的那些利益相关者 ID 的第一个数组。 新选择的利益相关者 ID 的第二个数组。 然后他会将这两个数组发送到我上面提到的各自的路由中。

如果我的架构师是对的,那么我没有问题,但我的前端开发人员应该如何处理编辑屏幕中的利益相关者选择?

我想澄清一点,我的联结表非常简单,除了 MeetingId 和 StakeholderId(一个非常基本的联结)之外,它不包含其他列。所以在这种情况下,在接收 StakeholderIds(整数列表)的“api/meetings/1/stakeholders”上创建单独的 POST/DELETE 操作是否有意义,而不是直接在 MeetingDto 中接收 StakeholderIds?

【问题讨论】:

  • pshh 建筑师...您的方法完全可以接受。 docs.microsoft.com/en-us/azure/architecture/best-practices/…。我从来没有见过任何参考说如果它有一个数组作为属性,你就不能 PUT 一个对象。正如您所解释的,他的方法确实限制了 API 所需的业务逻辑,但会给您的 UI 带来负担。您已经编写了 BL 来处理数组,所以我会保持原样。

标签: c# rest api asp.net-web-api many-to-many


【解决方案1】:

首先,如果我没记错的话:

  • 您有一个资源:“会议”;
  • 您想更新上述资源(使用 HTTP/PUT)。

因此,通过在“/api/meetings/:id”上请求 PUT 来更新会议似乎相当简单、简洁、直接和清晰。设计一个好的界面的所有好的特征。而且它仍然尊重单一职责原则:您正在更新资源”

尽管如此,我也同意架构师的意见,除了前面的方法之外,如果必要条件证明如此,则对“api/meetings/1/stakeholders”提供 POST/Delete 操作。我们应该在某种程度上务实,不要过度设计不需要的东西。

现在,如果您的架构师只是因为它是如何持续存在而这么说的,那么他就错了。最终用户应该清楚接口(今天的前端,明天的另一个服务或应用程序......),但最重要的是,在这种情况下,不知道它的持久性或任何与此相关的实现。

您的 api 应该关注您的域和业务规则,而不是您存储信息的方式。

这只是我的看法。如果有人不同意我的观点,我想被叫出来,这样双方就可以一起成长和学习。

:) 希望我能有所帮助。干杯

【讨论】:

  • 我想澄清一点,我的联结表非常简单,除了 MeetingId 和 StakeholderId(一个非常基本的联结)之外,它不包含其他列。所以在这种情况下,在“api/meetings/1/stakeholders”上创建单独的 POST/DELETE 操作是否有意义,以接收 StakeholderIds(整数列表)而不是直接在 MeetingDto 中接收 StakeholderIds??
  • 如果这是我看不到优势的唯一原因。如果会议和利益相关者模型都那么简单。我会保持 api 也很简单。您可以同时实现这两种方式 xD。但在我看来,第一个(你的想法)就足够了。
猜你喜欢
  • 2016-07-23
  • 2020-12-24
  • 2016-12-26
  • 2013-10-23
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多