从数据库上下文获取所有跟踪的实体
本文关键字:跟踪 实体 数据库 上下文 获取 | 更新日期: 2023-09-27 18:30:56
我的数据库中的许多表都需要有"DateCreated"和"DateModified"列。我想在调用SaveChanges()
时更新这些列。
我所有的模型对象都继承自允许这种行为的类AbstractModel
。该类如下所示:
public abstract class AbstractModel {
public virtual void UpdateDates() { }
}
然后,我计划覆盖任何子类中的UpdateDates()
,这些子类具有需要维护的DateCreated
和DateModified
字段。
要使用它,我需要能够获取DbContext
正在跟踪的所有实体的列表,并在对象标记为Added
或Modified
时调用UpdateDates()
。
我似乎无法访问DbContext
存储此信息的任何地方。我可以做dbContext.Entry(object).State
来获取单个实体的EntityState
,但我无法弄清楚如何获取所有跟踪实体的列表。
我该怎么做?
我认为您可以使用ChangeTracker来实现这一点:
public class MyContext : DbContext
{
//...
public override int SaveChanges()
{
foreach (var dbEntityEntry in ChangeTracker.Entries<AbstractModel>())
{
dbEntityEntry.Entity.UpdateDates();
}
return base.SaveChanges();
}
}
这里接受的解决方案对于上述 EF4 比 ObjectContext 建议更好 - 我们遇到了问题,例如我们在测试上下文中使用的内存数据库不能很好地与上述解决方案配合使用(在继承方案中为某些修改的条目获取分离状态)。此解决方案使用 DbContext 本机方式检索跟踪的实体:
context.ChangeTracker.Entries()
.Where (t => t.State == EntityState.Modified)
这在我们的项目中运行良好,因此我们不必记住每次添加具有标准 LastUpdateDateTime 属性的新实体时都重写某些内容。使用 EF4;对于 EF5 DbContext 我认为((IObjectContextAdapter)_dbContext)。ObjectContext.ObjectStateManager 会让你得到对象状态管理器:
// In our SaveChanges wrapper:
var entries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted);
private static void PopulateDate(IEnumerable<ObjectStateEntry> entries)
{
foreach (var entry in entries)
{
if (entry.State != EntityState.Deleted)
{
if ((entry.Entity != null) && (entry.Entity.GetType().GetProperty("LastUpdatedDateTime") != null))
{
((dynamic)entry.Entity).LastUpdatedDateTime = DateTime.UtcNow;
}
}
}
}
反射调用不是问题:对于具有 25 个属性(很多)的对象,一百万个反射查询平均需要 ~210 毫秒。