防止实体框架在软删除时清空外键



>我继承了一个 Web 应用程序,其数据库不删除行(出于审核原因),而是有一个"已删除"标志,在选择或连接表时必须检查该标志。它已被引入实体框架 5,为了自动化此系统,DbContext 已使用以下代码进行了修改:

public class DbContext : System.Data.Entity.DbContext
{
public override int SaveChanges()
{
var deletedEntities = ChangeTracker.Entries().Where(x=>x.State == EntityState.Deleted).ToArray();
foreach(var entityEntry in deletedEntities)
{
try
{
dynamic entity = entityEntry.Entity;
entity.Deleted = true;
entityEntry.State = EntityState.Modified;
}
catch(RuntimeBinderException)
{
//allow hard delete
}
}
return base.SaveChanges();
}
}

实际代码更复杂,因为它还可以设置更新时间、更新用户、检测新对象并设置其创建时间/用户等。

但是,当我们的对象具有与之关联的外键并且代码加载这些关联的对象时,我们遇到了一个问题。引用已删除对象的 FK 将清空。

EF 代码处于数据库优先模式,因为数据库早在公司决定切换到实体框架之前就已存在,并且数据库的 FK 约束都是"ON DELETE NO ACTION",因此如果 FK 遵循数据库的设计,我们不希望 FK 设置为 null。

我们知道实体框架不想孤立它们,但现有设计要求它们保持不变。我们期望并要求(出于审计原因)外键继续指向"已删除"行(同样,常规查询会过滤掉已删除的行)。这样做的一个原因是,如果客户打电话给我们"意外"删除某些内容,我们可以翻转旗帜,一切都会"正常工作"。我无法更改此设计。

例如,采用以下简化的场景代码:

//FooBarContext derives from the above DbContext and was generated from a database using Database First
using(var context = new FoobarContext())
{
var foo = context.FOO.Find(fooId);
var bar = foo.Bar;
context.BAR.Remove(bar);
context.SaveChanges();
}

所以我"删除"属于foo对象的Bar对象,Bar.Deleted设置为true,Bar被更新而不是删除。但是已加载到上下文中的 foo 对象会识别出 bar 对象已被"删除"和"foo"。BarId"设置为NULL,此更改在调用 SaveChanges 时传播。我们想要"foo。BarId"以保持相同的值。

有没有办法告诉实体框架停止在数据库优先模式下清空外键?

好吧,您将实体标记为已修改。

问题是,您标记的对象是否从数据库中加载并使用相同的上下文实例进行更新?

如果没有,在附加它们时,您是否使用正确设置的外键来附加它们(您可以在不传输 FK 值的情况下从视图模型或业务模型映射它们)?

因为,如果不是,EF 将向您求和您正在清空 FK(FK 中的 0 或空字符串在 db 方面为 NULL )。

相关内容

  • 没有找到相关文章

最新更新