【问题标题】:Proper solution to saves to multiple tables保存到多个表的正确解决方案
【发布时间】:2019-11-20 03:14:16
【问题描述】:

我正在使用 Dapper 作为 ORM 创建 ASP.NET Core 应用程序。

将对象保存到多个表中的正确流程是什么?

在我的应用架构中,我有标准的 Web api 控制器,它们调用命令/查询处理程序来计算/调用其他服务/存储库等。

我的实体/数据库表是用户、订单、产品。我的 CommandHandler 之一创建用户,然后计算产品、订单等。我只是想知道如何将这些对象保存到数据库中。我看到了 2 个解决方案:

1.) 我在命令处理程序期间为所有计算的内容创建某种 DTO:

public class TestDto
{
    public User User;
    public IList<Orders> Orders;
}   

计算所有东西,一一填充 DTO,然后在命令处理程序结束时调用所有存储库:

...using (var ts = new Transaction)
{
 _userRepository.Save(dto.User);
 _ordersRepository.Save(dto.Orders);

 ts.Complete
}

等等。

2.) 为整个命令处理程序创建事务,计算完用户后立即保存到内存中,然后计算订单并立即保存,订单也是如此。

【问题讨论】:

  • 如果一致性是最重要的,那么使用事务就是要走的路。然而,一致性并不总是必要的。事实上,大多数工程师都没有意识到根本不需要一致性。因此原子命令不是强制性的。您可以使您的方法具有幂等性。这将允许在不添加多个用户的情况下多次执行此逻辑。如果添加订单失败,您也可以删除用户。我们需要学会更加宽容,并为我们的系统增添一点优雅。
  • 因为作为工程师,您可以决定系统在某些状态下的行为方式。如果您创建一个可以处理这些情况的系统,那根本不是问题。但当然,这完全取决于一个人正在创建的系统。有时一致性是强制性的。在这种情况下,人们可能会争辩说用户仍然是用户,即使它还没有下过任何订单。或者即使用户未能成功下订单。如果是客户,讨论可能会完全不同。

标签: c# asp.net-core architecture dapper


【解决方案1】:

无论如何,您至少需要一笔交易。您不想保存不完整的订单。我说至少一个,因为这取决于您的用户是否可以与订单分开存在。

您可以先在一个事务中创建并保存用户,然后在第二个事务中保存订单。如果在保存订单时出现任何问题,您仍然需要将用户提交到数据库。使用选项 #2,您可以在命令处理程序中执行两个事务。

使用选项#1,我会担心引入一个将用户和订单绑定在一起的额外对象。您可能会发现有时需要单独更改用户或订单。 TestDto 不会有帮助。

【讨论】:

  • 因此,假设业务规则是保存全部或全部保存。所以我知道对于#1 中的这个要求,我必须在事务中结束所有这些存储库调用。那么问题是在内存中计算,到底保存,还是一边计算一边一个一个地保存?
  • 有人可能会争辩说这不应该是一个商业规则。但是一个实现细节。问题是,他们为什么要全部或全部保存。也许这是有道理的,但不是必须的。不一致的数据会导致不良行为。这是他们不想要的行为。但是,如果您的系统是健壮的,它就不必仅仅因为您的数据不完整而表现出不良行为。这是你的系统。从技术上讲,以最有意义的方式构建它。
猜你喜欢
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2011-01-15
  • 2018-08-30
  • 1970-01-01
相关资源
最近更新 更多