我的建议是你不应该SaveChanges()
为此修改你的代码。
使用 RLS 的推荐方法是使TenantId
列对您的 EF 模型和代码透明,因此您无需在实体中定义租户 ID 或导航属性。这样,除了打开数据库连接时,您无需更改SaveChanges()
代码,也无需在代码中的任何位置显式管理和设置值。Subscription_Id
您需要做的是Subscription_Id
在数据库的列中手动设置默认值约束,默认值基于当前会话Subscription_Id
参数。该值将在插入记录时设置,并隐式用于过滤数据库级别的任何后续查询和命令。
如果是新列:
ALTER TABLE SomeEntityTable ADD Subscription_Id nvarchar(128)
DEFAULT CAST(SESSION_CONTEXT(N'UserId') AS nvarchar(128))
如果是现有列:
ALTER TABLE SomeEntityTable
ADD DEFAULT CAST(SESSION_CONTEXT(N'UserId') AS nvarchar(128)
FOR Subscription_Id
如果该列具有先前的不同DEFAULT
值,最好也删除其关联的过时DEFAULT
约束。可以在此处找到有关更新现有列中的默认值的更多信息。
这些列不应包含在您的模型中。您的实体类中不应有它们的属性。如果您使用的是 Database First,您应该确保在从数据库更新模型时排除/忽略这些列。
如果您使用的是 EF Code First,如何执行此操作:您可以AlterColumn
在CreateColumn
使用Add-Migration
. 对每个实体表执行此操作:
public override void Up()
{
AlterColumn("dbo.SomeEntityTable", "Subscription_Id",
c => c.String(
nullable: false,
maxLength: 128,
defaultValueSql: "CAST(SESSION_CONTEXT(N'UserId') AS nvarchar(128))"));
}
(最好添加一个Down()
删除列的方法。)
警告Subscription_Id
:如果表中已有记录为空列值(或者如果要向已有记录的表中添加新列),则在运行此迁移时要小心Subscription_Id
。空列将填充Subscription_Id
正在执行迁移的连接中的值,这可能是错误的(您可能不希望所有现有记录都与该特定订阅相关联)。在这种情况下,您可能希望在方法中包含具有正确值的显式UPDATE
指令。像这样的东西:Subscription_Id
Up()
Sql()
Sql("UPDATE SomeEntitiesTable SET Subscription_Id= '19bc9b0d-28dd-4510-bd5e-d6b6d445f511' WHERE Id IN (1, 2, 5)");
使用 Code First,您还应该Subscription_Id
从模型类中删除属性。如果你不能,至少Ignore()
在你的配置代码中为这些Subscription_Id
列添加明确的说明,你不希望它们出现在你的 EF 映射中。
注意:我在这里假设您在数据库中创建了一个使用UserId
参数 in的 RLS 策略SESSION_CONTEXT
,并且您的应用程序代码在打开数据库连接时通过 aDbConnectionInterceptor
或类似的东西设置该值。
此页面包含更多信息。