5

我喜欢使用 Upsert 存储过程,如果记录存在则更新记录,如果不存在则插入记录。如果没有它们,我需要首先确定记录是否存在,然后根据结果调用两个单独的存储过程。

在今天之前,当我创建一个名为 UpdateOrDeleteRow 的存储过程时,我从未真正考虑过这个问题。当我发现自己在名称中包含“或”时,我的 SRP 蜘蛛意识就开始发挥作用,我意识到这些 upserts 基本上是一回事。

这是否违反 SRP?如果可以,是否可以接受?如果没有,我该怎么办?

我意识到 SRP 是 OOP 原则,而 T-SQL 不是 OOP 语言,但该原则的基础似乎也应该适用于此。

4

5 回答 5

4

还有一个比 SRP- DRY 更让我喜欢的原则。所以,如果你在一个地方调用这个序列,你可以考虑单一责任。但是当你多次重复相同的动作序列时,DRY 让我删除重复。

顺便说一句,我想到了,你可以避免OR在过程/方法名称中。UpdateOrInsert操作有很好的名字Save。我认为它不会破坏 SRP。

于 2012-05-15T21:40:45.583 回答
3

我个人不相信这个原则完全适用于 SQL Server。存储过程并不总是只执行一个动作(我认为存储过程等同于类的概念是有缺陷的)。我认为将存储过程中的每条语句拆分为自己的存储过程是没有意义的。你会变得非常荒谬。

当然有一个平衡,否则你可能会很荒谬。您不希望存储过程具有 18 种不同的方式来指定参数,以便它可以根据组合执行 540 种不同的事情。

对于 UPSERT,我仍然建议使用单个存储过程来解决此问题。如果您想让它更好地服务于单一目的,请将您的更新/插入更改为单个MERGE. :-) 话虽如此,说真的,要非常小心MERGE.

于 2012-05-15T21:46:07.320 回答
2

我不同意在这种情况下应该应用主体,因为它会在您的代码隐藏中产生一些冗余代码。

首先让我们检查一下您的 UPSERT 做了什么,它检查数据是否存在,然后根据它执行 INSERT 或 UPDATE。

在代码隐藏中,您必须对数据库进行 2 次调用,具体取决于应用程序的结构,这也可能意味着打开和关闭两个连接。

因此,您在代码隐藏中有 3 个方法(一个用于执行每个 proc),然后是一个方法来调用这些方法中的每一个并执行逻辑来决定是否需要插入或更新。

您的数据库中还有 3 个单独的存储过程来执行每个操作。

对我来说,这似乎是结构糟糕的代码,因为您将向插入/更新过程传递与向 upsert 传递相同的参数,因此在一个地方完成所有这些是有意义的。

通过使用 UPSERT,您有 1 个存储过程,并且只需要一个连接,其中一种方法可以从代码隐藏中调用。我认为这会产生更好、更简洁的代码。

于 2012-05-16T10:30:27.263 回答
1

如果您已经有独立执行更新或删除操作的过程,希望记录用于审计目的,您可以让您的 upsert 过程单独调用它们。这样,即使从多个位置调用它们,也只有那些 proc 正在做有助于保持事情可控的工作。

于 2012-05-15T21:38:07.690 回答
1

单一责任原则说,一个对象应该只有一个改变的理由。Upsert 存储过程应该更改的唯一原因是表结构是否更改。因此,我认为您可以创建 upsert 存储过程。

于 2012-05-15T21:39:30.493 回答