【问题标题】:Preventing Entity Framework from nulling out foreign keys when soft deleting防止实体框架在软删除时清除外键
【发布时间】:2018-08-14 16:45:17
【问题描述】:

我继承了一个 Web 应用程序,其数据库不删除行(出于审计原因),而是有一个“已删除”标志,在选择或加入表格时必须检查该标志。它已被引入 Entity Framework 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代码是Database First模式,因为数据库早在公司决定切换到Entity Framework之前就已经存在了,而且数据库的FK约束都是“ON DELETE NO ACTION”,所以我们不希望FK如果它遵循数据库的设计,则设置为 null。

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

以这个简化的场景代码为例:

//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”保持相同的值。

有什么方法可以告诉 Entity Framework 在数据库优先模式下停止将外键归零?

【问题讨论】:

标签: c# entity-framework ef-database-first


【解决方案1】:

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

问题是,您要标记的对象,它们是从数据库加载并使用相同的上下文实例更新的区域吗?

如果不是,那么在附加它们时,您是否使用正确设置的外键附加它们(您可以从视图模型或业务模型映射它们而无需传输 FK 值)?

因为,如果不是,EF 将假定您正在使 FK 为空(FK 中的 0 或空字符串是 NULL db-wise)。

【讨论】:

    猜你喜欢
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多