覆盖SaveChanges并删除EF关系时为空

时间:2016-07-08 18:35:38

标签: c# asp.net entity-framework-6

在我的多对一关系中,我试图删除其中一个子对象,并在我重写的SaveChanges中保留审计跟踪。

当执行EntityState.Modified或EntityState.Added时,file.Entity.Product不为null但是在执行.Deleted EF时,即使在调用base.Savechanges()之前,似乎正在积极地从实体中删除关系。< / p>

在File(child)上调用.Remove后,有什么方法可以检索Product我的SaveChanges覆盖中与Product相关联的文件吗?

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);
            }

4 个答案:

答案 0 :(得分:2)

正如您在ChangeTracker条目中找到该文件一样,您可以找到其产品,假设FileProduct具有外键关联 },即它除了ProductID导航属性外还有Product属性:

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);
    }
}

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

答案 1 :(得分:1)

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

但是,为什么不使用软删除,这是我认为的最佳做法,如果被错误删除,你可以随时返回已删除的记录(通过标记IsDeleted = false,由管理员授权)

希望这会对你有所帮助

答案 2 :(得分:0)

如果仅需要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; }
   }
   ...
}

答案 3 :(得分:0)

Gert Arnold提供的答案应该有效 - 但不确定检查是否有意义      FirstOrDefault(p =&gt; 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插入查询以填充审计表?