实体框架6:检测关系发生变化 [英] Entity Framework 6: detect relationship changes

查看:104
本文介绍了实体框架6:检测关系发生变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的DbContext子我已经覆盖了调用SaveChanges()方法,这样我就可以实现一种类似触发的functionalilty的(实际上是保存更改之前)。
现在,在其中的一些触发它需要检测的某些关系是否已经改变,而不管多对许多人来说,一对一/零等

in my DbContext subclass I have overridden the SaveChanges() method so I can implement a sort of Trigger-like functionalilty (before the changes are actually saved). Now, in some of these triggers it is necessary to detect whether certain relationships have changed, regardless of many-to-many, one-to-one/zero etc.

我已阅读在互联网上的一些帖子,包括一些在这个网站,这提的是,API的DbContext未公开获得的信息关系的任何手段。
然而,ObjectContext的应能

I have read a number of posts on the internet, including some on this site, that mention that the DbContext API doesn't expose any means of getting relationship info. However, ObjectContext should be able to.

我的SaveChanges方法:

My SaveChanges method:

public 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的集合。

Note the four variables added, updated, deleted and unchanged. According to what I've found so far, the GetObjectStateEntries is supposed to return a collection of ObjectStateEntry, which has a property IsRelationship.

我运行下面的在测试应用程序代码:

I run the following code in a test application:

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的代码中,我得到什么预期:
一个结果在更新列表,客户对象。
,而在任何时候我曾经得到一个ObjectStateEntry的关系(一比一)Customer_Address

When I inspect the code in SaveChanges after that call, I get what was expected: one result in the updated list, the Customer object. But at no point do I ever get an ObjectStateEntry for the relationship (one-to-one) Customer_Address.

我需要能够如先前检测当的关系已经改变所述。
对于普通的标量属性你可以这样做:

I need to be able to detect as previously described when the relationship has changed. For normal scalar properties you would do this:

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



但并不明显工作的参考属性。
任何想法?

But for reference properties that doesn't work obviously. Any ideas?

推荐答案

您可以使用此 ExtensionMethod 要得到改变。

You can use this ExtensionMethod to get a list of relationships that changed

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, (e, 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))));
    }
}

这篇关于实体框架6:检测关系发生变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆