背景
我有一个多租户方案和一个独特的Sql Server项目,它将被部署到同一服务器上的多个数据库实例中。每个租户将有一个数据库,加上一个"模型"分贝。
"模型"数据库有三个目的:
有些触发器会检查租户数据库中的已修改/已删除数据是否与" system" "模型中的数据" D b。如果是,则会出现错误,指出系统数据无法更改。
问题
因此,这是触发器的一部分,用于检查是否允许删除:
IF DB_NAME() <> 'ModelTenant' AND EXISTS
(
SELECT
[deleted].*
FROM
[deleted]
INNER JOIN [---MODEL DB NAME??? ---].[MySchema].[MyTable] [ModelTable]
ON [deleted].[Guid] = [ModelTable].[Guid]
)
BEGIN;
THROW 50000, 'The DELETE operation on table MyTable cannot be performed. At least one targeted record is reserved by the system and cannot be removed.', 1
END
我似乎无法找到应该取代的地方--- MODEL DB NAME ??? ---在上面的代码中,允许项目正确编译。在引用完全不同的项目时,我知道该怎么做:使用对SQLCMD变量表示的项目的引用。但在这种情况下,项目参考基本上是同一个项目;仅在不同的数据库上。我似乎无法以这种方式添加自引用。
我该怎么办? SSDT是否为这种情况提供某种支持?
答案 0 :(得分:1)
您是否尝试过设置数据库变量?您可以在"Reference aware statements" here下阅读。然后你可以说:
SELECT * FROM [$(MyModelDb)][MySchema].[MyTable] [ModelTable]
如果您没有$(MyModelDb)
的特定项目,可以选择“通过未解析的引用来抑制错误......”。自从我使用SSDT项目以来,它一直是永恒的,但我认为这应该有用。
提示:如果需要100次引用1表,您可能会发现创建使用数据库变量的SYNONM更好,然后指向SPROC / TRIGGER中的SYNONM。为什么?因为这样您就不需要部署SPROC / TRIGGER来将变量替换为实际值,这可以使开发更加顺畅。
答案 1 :(得分:1)
我不太确定SSDT是否特别适合任何体面复杂的项目。我可以想到一种或两种最有可能实现这一目标的方法(特别是取决于你如何进行发布/部署),但我认为你实际上会失去的比你获得的更多。我的意思是:你可以添加步骤来实现这一点(即赢得战斗),但你会创建一个更复杂的系统,以便让SSDT发布一个比复杂(和更慢)更复杂的系统它需要(即输掉战争)。
在担心SSDT之前,让我们先看看你为什么需要SSDT来做这件事。您将系统数据与租户数据混合在一起,您需要验证UPDATE
和DELETE
操作以确保系统数据不会被修改,并且是识别数据的唯一方法。系统&#34;数据是通过将其与记录主页 - ModelDB
相匹配 - 基于GUID PK。
关于识别哪些数据属于&#34;系统的理论&#34;而不是租户是你的主要问题,而不是SSDT。通过使用&#34;模型&#34;您绝对可以通过多帐篷系统走上正轨。数据库,但使用它进行数据验证是一个糟糕的设计选择:除了使用GUID作为PK已经导致性能下降之外,您还通过漏斗进一步降低了所有这些UPDATE
和DELETE
操作的速度它们通过单点争用,因为所有客户端DBS都需要检查此公共源。
最好在每个表中包含一个BIT
字段,用于混合系统和租户数据,表示该行是否是&#34; system&#34;或不。只需查看SQL Server中的系统目录视图:
sys.objects
有一个is_ms_shipped
列sys.assemblies
走向另一个方向,并有is_user_defined column
。因此,如果您要向这些表添加[IsSystemData] BIT NOT NULL
列,您的触发器逻辑将变为:
IF DB_NAME() <> N'ModelTenant' AND EXISTS
(
SELECT del.*
FROM [deleted] del
WHERE del.[IsSystemData] = 1
)
BEGIN
;THROW 50000, 'The DELETE operation on table MyTable cannot be performed. At least one targeted record is reserved by the system and cannot be removed.', 1;
END;
优点:
UPDATE
和DELETE
次操作ModelDB
)答案 2 :(得分:1)
作为引用另一个数据库项目的替代方法,您可以生成一个dacpac,然后将dacpac作为数据库引用引用到相同的服务器,不同的数据库&#34;模式。