在我的多对一关系中,我试图删除其中一个子对象,并在我重写的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);
}
答案 0 :(得分:2)
正如您在ChangeTracker
条目中找到该文件一样,您可以找到其产品,假设File
与Product
具有外键关联 },即它除了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插入查询以填充审计表?