C# 使用附加子句更新实体

C# 使用附加子句更新实体,c#,asp.net,.net,entity-framework,entity-framework-core,C#,Asp.net,.net,Entity Framework,Entity Framework Core,我目前正在开发一个基于专栏的多租户应用程序。 我在每个实体上添加了一个带有基类的tenantId,并使用了完全符合我需要的查询过滤器。 我还重写了savechanges方法,使用changetracker在添加的实体上填充tenantid属性 但现在我被更新和删除所困扰。 据我所知,ef生成了一个只有主键的where子句,这对我来说是非常不安全的,因为我在一个api环境中使用了大量的attach/detach内容,并编写了大量的entity.state=modified,而不是首先查询,以提高性

我目前正在开发一个基于专栏的多租户应用程序。 我在每个实体上添加了一个带有基类的tenantId,并使用了完全符合我需要的查询过滤器。 我还重写了savechanges方法,使用changetracker在添加的实体上填充tenantid属性

但现在我被更新和删除所困扰。 据我所知,ef生成了一个只有主键的where子句,这对我来说是非常不安全的,因为我在一个api环境中使用了大量的attach/detach内容,并编写了大量的entity.state=modified,而不是首先查询,以提高性能

我的问题是:如何向ef core update/delete语句添加谓词

我知道我可以: 1.先问一下,我相信你会推荐我的 2.将tenantid作为compositekey的一部分,但由于add/find/etc方法需要完整的主键,因此重构我的所有代码将非常痛苦

我真的很感激任何知道如何触发这一切的人

选项3:

尽管不是为此设计的,但您可以使用EF Core为您执行安全检查:

在关系数据库上,EF Core在任何UPDATE或DELETE语句的WHERE子句中检查并发令牌的值。执行语句后,EF Core读取受影响的行数。 如果没有行受到影响,将检测到并发冲突,EF Core将抛出DbUpdateConcurrencyException

想法是1通过[ConcurrencyCheck]属性或IsConcurrencyToken fluent API将TenantId标记为并发令牌,2在SaveChanges覆盖中,使用当前租户Id设置TenantId属性值,不仅用于添加的实体,也用于修改和删除的实体

通过这样做,EF Core将添加类似于和TenantId=@currentTenantId的内容来更新和删除命令,只有当当前租户与用于创建实体的租户匹配时,更新和删除命令才会成功

缺点是异常类型/消息,如果使用,会与现有的并发检查混合

更新:SaveChanges中已修改和已删除实体的代码应设置TenantId属性项的原始值,并重置IsModified标志:


如果TenantId属性配置为AfterSaveBehavior=PropertySaveBeheavior,则不需要最后一个。请按照中的说明忽略。

您在EF Core中尝试过全局查询筛选器吗?当然!但筛选器仅在选择查询上执行..请尝试建议的解决方案1,按租户和其他列检索实体,然后更新实体显然,解决方案1功能齐全,但性能会受到影响,您确定没有针对此问题的预构建解决方案吗?作为一般性意见,我认为您不应该将整个实体标记为已修改,而应该只标记选定的属性。仅此一点就足以防止租户被标记为已修改。为了使它更安全,你可以使用。我知道应该有一些东西给我,非常感谢你的知识,这是完美的预期工作!事件,如果我必须通过设置currentValue更新条目来更新属性。实体不起作用,对于您可以看到的那个些。欢迎使用。我更新了答案,提供了更多关于如何处理内部SaveChanges的信息。WHERE中使用的值实际上是OriginalValue,它通常包含来自数据库的值,但在断开连接的场景中,是对象附加到上下文更新/删除方法时的属性值。虽然不是为此而设计的-这是一个魔鬼:@GertArnold在这里我是:在保加利亚,我们说的是“不确定翻译”可怜的人-活着的魔鬼。在这种情况下-使用MS给我们的任何东西:很高兴看到你心情愉快,希望你做得很好。
var tenantIdEntry = entityEntry.Property("TenantId");
tenantIdEntry.OriginalValue = CurrentTenantId;
tenantIdEntry.IsModified = false;