我数据库中的许多表都需要有一个“DateCreated”和“DateModified”列。我想在调用SaveChanges()
时更新这些列。
我的所有模型对象都继承自类AbstractModel
以允许这种行为。该课程如下:
public abstract class AbstractModel {
public virtual void UpdateDates() { }
}
然后我计划在任何需要维护UpdateDates()
和DateCreated
字段的子类中覆盖DateModified
。
要使用此功能,我需要能够获取DbContext
正在跟踪的所有实体的列表,如果对象标记为{{1},则需要在其上调用UpdateDates()
}或Added
。
我似乎无法访问Modified
存储此信息的位置。我可以DbContext
获取单个实体的dbContext.Entry(object).State
,但我无法弄清楚如何获取所有跟踪实体的列表。
我该怎么做?
答案 0 :(得分:21)
我认为您可以使用ChangeTracker:
public class MyContext : DbContext
{
//...
public override int SaveChanges()
{
foreach (var dbEntityEntry in ChangeTracker.Entries<AbstractModel>())
{
dbEntityEntry.Entity.UpdateDates();
}
return base.SaveChanges();
}
}
答案 1 :(得分:5)
对于上面的EF4,接受的解决方案here比ObjectContext建议更好 - 我们遇到了问题,例如我们在测试上下文中使用的内存db与上述解决方案不兼容(获得Detached状态为继承方案中的一些修改条目)。此解决方案使用DbContext本机方式检索跟踪的实体:
private IEnumerable<IValidationResult> Validate(IDeliveryObject deliveryObject)
{
var validationErrors = new List<IValidationResult>();
int maxNumberOfErrors = 10;
foreach (IDeliveryValidator deliveryValidator in _validators)
{
// Here I want results to contain MAX 10 regular validation results, but unlimited soft validation results
IEnumerable<IValidationResult> results = deliveryValidator.Validate(deliveryObject).Take(maxNumberOfErrors);
validationErrors.AddRange(results);
if (validationErrors.Count(x => !x.IsSoftError) >= maxNumberOfErrors)
{
return validationErrors.Take(maxNumberOfErrors).ToList();
}
}
return validationErrors;
}
答案 2 :(得分:2)
这在我们的项目中运作良好,因此每次添加具有标准LastUpdatedDateTime属性的新实体时,我们都不必记住覆盖某些内容。 使用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 ms。