在EF Core环境中更新特定实体条目

时间:2019-03-25 18:08:42

标签: entity-framework entity-framework-core dbcontext

我正在使用DbContext范围实现。基本上,这意味着我将继续使用环境DbContext方法。 More information

我简化了我的真实代码,并删除了与上下文流行为有关的所有逻辑...

using (var dbContextParentScope = ...)
{
    DbContext parentContext = dbContextParentScope.Get<ApplicationContext>();

    // that data will be in the DbContext cache
    var accounts = parentContext.Accounts.ToList();

    // this is always part of a separate method
    using (var dbContextChildScope = ...)
    {
        DbContext childContext = dbContextChildScope.Get<ApplicationContext>();

        var childAccounts = childContext.Accounts.ToList();
        childAccounts.ForEach(a => a.DisplayName = "New name");

        // after that operation parentContext data will be outdated
        childContext.SaveChanges();

        // this will reload updated entities in the parentContext
        dbContextChildScope.RefreshEntitiesInParentScope(childAccounts);
    }

    // without Refresh operation we will work with outdated data
    parentContext.SaveChanges();
}

这是例外情况,但是有时我们必须在重要交易之外保存重要信息。

实体框架有可能从DbContext中通过键获取记录:

if (((IObjectContextAdapter)childContext).ObjectContext.ObjectStateManager.TryGetObjectStateEntry(childAccounts[0], out ObjectStateEntry stateInChildScope))
{
    var key = stateInChildScope.EntityKey;

    if (((IObjectContextAdapter)parentContext).ObjectContext.ObjectStateManager.TryGetObjectStateEntry(key, out ObjectStateEntry stateInParentScope))
    {
        if (stateInParentScope.State == EntityState.Unchanged)
        {
            ((IObjectContextAdapter)parentContext).ObjectContext.Refresh(RefreshMode.StoreWins, stateInParentScope.Entity);
        }
    }
}

EF Core没有此类功能,但具有'ChangeTracker'。它可以返回DbContext正在跟踪的条目:

parentContext.ChangeTracker.Entries().Where(w => w.State == EntityState.Unchanged).ToList()

但是我只想重新加载childContext中更新的记录。所以,如果我写这样的话:

var updatedEntry = childContext.Entry(childAccounts[0]);
parentContext.Entry(updatedEntry.Entity).Reload();

EF Core会像对待newEntry一样思考它,并且会抛出System.InvalidOperationException:

  

无法跟踪实体类型'Account'的实例,因为已经跟踪了另一个具有相同'{'EntityId'}关键字值的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。

我还发现了一些内部功能,但是我不想使用内部EF Core代码(只是这是使其正常工作的唯一方法),因为可以对其进行更改/删除:

var entityType = parentContext.Model.FindEntityType(typeof(TEntityType));
var key = entityType.FindPrimaryKey();
var stateManager = parentContext.GetDependencies().StateManager;
var keysDictionary = key.Properties.ToDictionary(x => x.Name, x => x.PropertyInfo.GetValue(childAccounts[0]));
var entry = stateManager.TryGetEntry(key, keysDictionary.Values.ToArray());
parentContext.Entry(entry.Entity).Reload();

有人知道如何从父上下文更新实体吗?

我希望得到您的帮助,因为我被困在这里,没有任何想法

0 个答案:

没有答案