在我的 DbContext 子类中,我重写了 SaveChanges() 方法,因此我可以实现一种类似触发器的功能(在实际保存更改之前)。
现在,在其中一些触发器中,有必要检测某些关系是否发生了变化,无论是多对多、一对一/零等。
我在互联网上阅读了许多帖子,包括本网站上的一些帖子,其中提到 DbContext API 不公开任何获取关系信息的方法。
不过,ObjectContext 应该可以。
我的 SaveChanges 方法:
public override int SaveChanges()
{
IEntity entity;
ChangeTracker.DetectChanges();
var stateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager;
var added = stateManager.GetObjectStateEntries(EntityState.Added).ToList();
var updated = stateManager.GetObjectStateEntries(EntityState.Modified).ToList();
var deleted = stateManager.GetObjectStateEntries(EntityState.Deleted).ToList();
var unchanged = stateManager.GetObjectStateEntries(EntityState.Unchanged).ToList();
while ((entity = _entitiesRequiringTriggering.FirstOrDefault(x => x.Value).Key) != null)
{
_entitiesRequiringTriggering[entity] = false;
var entry = ChangeTracker.Entries<IEntity>().SingleOrDefault(x => x.State != EntityState.Unchanged && x.Entity == entity);
if (entry == null) continue;
var trigger = Triggers.Triggers.GetTriggerForEntity(entry.Entity, this);
if (trigger == null) continue;
trigger.BeforeSave(entry.Entity);
switch (entry.State)
{
case EntityState.Added:
trigger.BeforeAdd(entry.Entity);
break;
case EntityState.Modified:
trigger.BeforeUpdate(entry.Entity);
break;
case EntityState.Deleted:
trigger.BeforeDelete(entry.Entity);
break;
}
}
return base.SaveChanges();
}
注意四个变量added, updated, deleted and 不变。
根据我到目前为止所发现的,GetObjectStateEntries 应该返回一个 ObjectStateEntry 的集合,它有一个属性 IsRelationship。
我在测试应用程序中运行以下代码:
using (var db = container.Resolve<IDatabaseContext>())
{
var cus = db.Query<Customer>().Single(x => x.Id == 1);
var newAddress = db.Query<Address>().Single(x => x.Id == 5);
cus.Address = newAddress; //also sets the foreign key property Customer.AddressId to its new corresponding value
db.SaveChanges();
}
当我在调用后检查 SaveChanges 中的代码时,我得到了预期的结果:
一个结果是updated列表,客户对象。
但我从来没有获得过关系(一对一)Customer_Address 的 ObjectStateEntry。
我需要能够如前所述检测关系何时发生变化。
对于普通标量属性,您可以这样做:
var changed = DbEntry.Property(x => x.Name).OriginalValue == DbEntry.Property(x => x.Name).CurrentValue;
但对于参考属性来说,显然不起作用。
有任何想法吗?