我目前正在开发基于列的多租户应用程序。 我在带有基类的每个实体上添加了tenantId,并使用了完全符合我需要的查询过滤器。 我还重写了savechanges方法,以使用changetracker在添加的实体上填充tenantid属性。
但是现在我被更新和删除所困扰。 据我所知,ef生成仅具有主键的where子句,这对我来说是非常不安全的,因为我在具有很多附加/分离内容的api环境中工作,并编写了很多entity.state = Modifyed首先是查询,以提高性能。
我的问题是:如何在ef核心更新/删除语句中添加谓词?
我知道我可以: 1.首先查询(我很确定你会建议我这样做) 2.将tenantid用作Compositekey的一部分,但是要将我的所有代码重构为add / find / etc确实很痛苦。方法需要完整的主键。
我将非常感谢任何知道如何触发此操作的人!
答案 0 :(得分:2)
选项3:
尽管不是为此而设计的,但是您可以使用EF Core Optimistic concurrency control为您执行安全检查:
在关系数据库上,EF Core包含对任何
WHERE
或UPDATE
语句的DELETE
子句中并发令牌值的检查。执行这些语句后,EF Core读取受影响的行数。 如果没有受影响的行,则检测到并发冲突,并且EF Core抛出DbUpdateConcurrencyException
。
想法是(1)通过TenantId
属性或[ConcurrencyCheck]
流利的API将IsConcurrencyToken()
标记为并发令牌,并且(2)在SaveChanges
覆盖内,使用当前租户TenantId
设置Id
属性值,不仅用于添加实体,还用于修改和删除实体。
这样做,EF Core将在AND TenantId == @currentTenantId
和UPDATE
命令中添加类似DELETE
的命令,只有当当前租户与用于实体创建的租户匹配时,该命令才能成功。
缺点是异常类型/消息,并与现有的并发检查(如果使用)混合在一起。
更新:SaveChanges
中用于修改和删除实体的代码应设置OriginalValue
属性条目的TenantId
并重置IsModified
标记:
var tenantIdEntry = entityEntry.Property("TenantId");
tenantIdEntry.OriginalValue = CurrentTenantId;
tenantIdEntry.IsModified = false;
如果TenantId
属性已按照What is the best way to perform partial updates in EF core and never update certain properties?中的说明配置为AfterSaveBehavior = PropertySaveBehavior.Ignore
,则不需要最后一个。