重写“保存更改”并删除 EF 关系时为空

本文关键字:保存更改 关系 EF 删除 重写 | 更新日期: 2023-09-27 17:56:08

在我的多对一关系中,我正在尝试删除其中一个子对象,并在我覆盖的 SaveChanges 中保留审计跟踪。

该文件。Entity.Product 在执行 EntityState.Modified 或 EntityState.Add 时不为 null,但在执行 .删除的 EF 似乎甚至在 base 之前就积极地从实体中删除关系。savechanges() 被调用。

在我调用 .删除文件(子)?

var files = from e in ChangeTracker.Entries<SavedFile>()
                    where e.State != EntityState.Unchanged
                    select e;
if (file.State == EntityState.Deleted)
            {
                var text = "File Deleted: " + file.Entity.FriendlyFileName;
                // file.Entity.Product is null
                var updatedProduct = new Update { Product = file.Entity.Product, UpdateDateTime = DateTime.Now, UpdateText = text, User = HttpContext.Current.Request.LogonUserIdentity.Name };
                Updates.Add(updatedProduct);
            }

重写“保存更改”并删除 EF 关系时为空

就像你在ChangeTracker的条目中找到文件一样,你可以找到它的产品,假设FileProduct有外键关联,即除了Product导航属性之外,它还具有ProductID属性:

if (file.State == EntityState.Deleted)
{
    var text = "File Deleted: " + file.Entity.FriendlyFileName;
    var productEntry = ChangeTracker.Entries<Product>()
                                    .FirstOrDefault(p => p.Entity.ID == file.ProductID);
    if (productEntry != null)
    {
        var updatedProduct = new Update { Product = productEntry.Entity, UpdateDateTime = DateTime.Now, UpdateText = text, User = HttpContext.Current.Request.LogonUserIdentity.Name };
        Updates.Add(updatedProduct);
    }
}

预期行为是,每当从本地缓存查询实体时,EF 都不会显示已删除的实体(例如 DbSet.Local )。因此,它还必须断开关联,以防止这些实体出现在导航属性中。如果删除文件,EF 不会以 context.Files.Local 显示该文件,但它也不会在导航属性(如 product.Files)中可见(关联的另一端也不会file.Product)。

我认为删除后无法访问关系船

但是,为什么不使用软删除,在我看来这是

最佳实践,如果被错误删除,您可以随时返回已删除的记录(通过标记 IsDelete = false,由具有权限的管理员)

希望这对你有帮助

如果只需要 Product 属性使用它,则可以在其定义上使用一些自定义逻辑来捕获它:

class File {
   ...
   private Product product;
   private Product lastProduct;
   public Product Product {
      get { return product; }
      set {
          if (product == value) return;
          lastProduct = Product;
          product = value;
      }
   }
   [NotMapped]
   public Product LastProduct {
      get { return lastProduct; }
   }
   ...
}

Gert Arnold 提供的答案应该有效 - 但不确定检查是否有意义 FirstOrDefault(p => p.State != EntityState.Unchanged因为相关实体可能仍处于"未更改"状态。

如果没有任何效果,请尝试在重写的 SaveChanges 方法中重新加载实体。

this.Entry((file.Entity as <<Your Entity Type>>)).Reload();
//do your operation/audit log
//then reset the Entity State to Deleted
this.Entry((file.Entity)).State = EntityState.Deleted;

编辑:或仅显式加载所需的相关实体

this.Entry(file.Entity as <Type>).Reference(e=> e.Product).Load();

这最终会在重新加载时造成额外的数据库命中。

编辑:另一个选项,如果没有找到其他好的选项

如何在此方案中执行原始 SQL 插入查询以填充审核表?