加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 实体框架6:检测关系变化

发布时间:2020-12-15 08:23:46 所属栏目:百科 来源:网络整理
导读:在我的DbContext子类中,我重写了SaveChanges()方法,因此我可以实现一种类似触发器的功能(在实际保存更改之前). 现在,在某些触发器中,有必要检测某些关系是否已经改变,无论多对多,一对一/零等. 我已经阅读了互联网上的一些帖子,包括本网站上的一些帖子,提到Db
在我的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();
}

请注意添加,更新,删除和更改的四个变量.
根据我到目前为止所发现的,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中的代码时,我得到了预期的结果:
一个结果在更新列表中,Customer对象.
但在任何时候,我都没有获得关系(一对一)Customer_Address的ObjectStateEntry.

我需要能够在关系发生变化时如前所述进行检测.
对于正常的标量属性,您可以这样做:

var changed = DbEntry.Property(x => x.Name).OriginalValue == DbEntry.Property(x => x.Name).CurrentValue;

但对于不明显起作用的参考属性.
有任何想法吗?

解决方法

您可以使用此ExtensionMethod获取已更改的关系列表
public static class DbContextExtensions
{
    public static IEnumerable<Tuple<object,object>> GetRelationships(
        this DbContext context)
    {
        return GetAddedRelationships(context)
                .Union(GetDeletedRelationships(context));
    }

    public static IEnumerable<Tuple<object,object>> GetAddedRelationships(
        this DbContext context)
    {
        return GetRelationships(context,EntityState.Added,(e,i) => e.CurrentValues[i]);
    }

    public static IEnumerable<Tuple<object,object>> GetDeletedRelationships(
        this DbContext context)
    {
        return GetRelationships(context,EntityState.Deleted,i) => e.OriginalValues[i]);
    }

    private static IEnumerable<Tuple<object,object>> GetRelationships(
        this DbContext context,EntityState relationshipState,Func<ObjectStateEntry,int,object> getValue)
    {
        context.ChangeTracker.DetectChanges();
        var objectContext = ((IObjectContextAdapter)context).ObjectContext;

        return objectContext.ObjectStateManager
                            .GetObjectStateEntries(relationshipState)
                            .Where(e => e.IsRelationship)
                            .Select(
                                    e => Tuple.Create(
                                            objectContext.GetObjectByKey((EntityKey)getValue(e,0)),objectContext.GetObjectByKey((EntityKey)getValue(e,1))));
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读