【问题标题】:How to Refresh DbContext如何刷新 DbContext
【发布时间】:2013-08-11 08:03:46
【问题描述】:

我想刷新我的DbContext 的所有实体而不重新创建它,我尝试了以下方法,但它们都没有意义:

var context = ((IObjectContextAdapter)myDbContext).ObjectContext;

var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(
                                   EntityState.Added
                                   | EntityState.Deleted
                                   | EntityState.Modified
                                   | EntityState.Unchanged)
                          where entry.EntityKey != null
                          select entry.Entity);

context.Refresh(RefreshMode.StoreWins, refreshableObjects);
//.......................................................................
foreach (var entry in this.Orm.ChangeTracker.Entries())
{
    entry.State = EntityState.Unchanged;
}
this.Orm.ChangeTracker.DetectChanges();

也是唯一一个刷新了我的DbContext

foreach (var i in this.Orm.ChangeTracker.Entries())
    i.Reload();

但是太慢了。您能帮我选择正确的方式吗?

【问题讨论】:

  • 你尝试过 context.Refresh(RefreshMode, Entity) 并在调试器和 sql 监视器中查看它是否真的更新了?
  • @yonexbat:我手动更改了 sql 中的数据并调用了context.Refresh(RefreshMode, Entity),但没有更新更改,并使用i.Reload(); 完成了相同的场景,所有更改都在我的DbContext 中更新。

标签: c# entity-framework entity-framework-4 refresh dbcontext


【解决方案1】:

我刚刚发现Enumerable 结果应该被评估,因为Refresh 方法将它作为对象获取并且不评估它。

var context = ((IObjectContextAdapter)myDbContext).ObjectContext;
var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries(
                                           EntityState.Added
                                           | EntityState.Deleted
                                           | EntityState.Modified
                                           | EntityState.Unchanged)
                          where entry.EntityKey != null
                          select entry.Entity).ToList();

context.Refresh(RefreshMode.StoreWins, refreshableObjects);

我更喜欢以下内容:

var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c=>c.Entity).ToList();
context.Refresh(RefreshMode.StoreWins, refreshableObjects);

【讨论】:

  • 使用你的方法,我得到:要刷新的对象集合中索引0处的元素处于添加状态。处于此状态的对象无法刷新。
  • @isti_spl:你最好在引用之前回滚if (entry.State==EntityState.Added) entry.State = EntityState.Detached;//...
  • 你拯救了我的一天 Mohsen :D
  • 我得到的和@isti_spl 一样,但我不清楚分辨率是什么。我们如何处理已添加状态?
  • @YeahStu 您根本不会从上面的代码中删除 EntityState.Added 。从正在添加的商店中刷新实体是没有意义的。它们尚不存在于商店中。
【解决方案2】:

我检查了这个并且 id 工作正常:

//Search
Box box = dbContext.Boxes.FirstOrDefault(x => x.BoxId == 45);

//breakpoint here, change Name of Box by sql management studio

//Refresh
var context = ((IObjectContextAdapter)dbContext).ObjectContext;
context.Refresh(System.Data.Entity.Core.Objects.RefreshMode.StoreWins, box);

//Check refresh and if it is in context
box = dbContext.Boxes.FirstOrDefault(x => x.BoxId == 45);

你确定是同一个 db-context 吗?

【讨论】:

  • 很抱歉将其添加为答案,但我不知道如何格式化评论中的文本。
  • :谢谢,我用它来刷新单个实体,但我需要刷新我的DbContext 的所有实体,而不仅仅是单个EntityEntity CollectionRelated Entities of some Entity。跨度>
  • 好的。我会重新创建 DbContext。 myDbContext = new MyDbContext();
  • :谢谢,但正如我上面提到的,我不想这样做。
  • 这看起来很完美。太糟糕了,我在不存在的 .Net Core 中。
【解决方案3】:

在某些情况下,如果某个集合已被第三方应用更新,则在刷新该集合的对象时可能不会重新加载该集合。

我有一个对象 A 与对象 B 有一对多关系的情况。

应用程序 1 加载 A.ListB 为空的对象 A。 应用程序 2 填充 A.ListB 集合。 应用程序 1 重新加载对象 A。

使用上述解决方案,A.ListB 仍然为空。我必须明确地重新加载集合 A.ListB。

这是重新加载所有集合的通用方法:

var context = ((IObjectContextAdapter)this).ObjectContext;

// detach all added entities
ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList().ForEach(e => e.State = EntityState.Detached);

// select entities
var refreshableObjects = ChangeTracker.Entries().Select(e => e.Entity).ToList();

// refresh each refreshable object
foreach (var @object in refreshableObjects)
{
    // refresh each collection of the object
    context.ObjectStateManager.GetRelationshipManager(@object).GetAllRelatedEnds().Where( r => r.IsLoaded).ToList().ForEach( c => c.Load() );

    // refresh the object
    context.Refresh(RefreshMode.StoreWins, @object);
}

【讨论】:

    【解决方案4】:
    using System.Data.Entity.Core.Objects;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    
    namespace System.Data.Entity
    {
        public static class DbContextExtensions
        {
            /// <summary>
            /// Refresh non-detached entities
            /// </summary>
            /// <param name="dbContext">context of the entities</param>
            /// <param name="refreshMode">store or client wins</param>
            /// <param name="entityType">when specified only entities of that type are refreshed. when null all non-detached entities are modified</param>
            /// <returns></returns>
            public static DbContext RefreshEntites(this DbContext dbContext, RefreshMode refreshMode, Type entityType)
            {
                //https://christianarg.wordpress.com/2013/06/13/entityframework-refreshall-loaded-entities-from-database/
                var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
                var refreshableObjects = objectContext.ObjectStateManager
                    .GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged)
                    .Where(x => entityType == null || x.Entity.GetType() == entityType)
                    .Where(entry => entry.EntityKey != null)
                    .Select(e => e.Entity)
                    .ToArray();
    
                objectContext.Refresh(RefreshMode.StoreWins, refreshableObjects);
    
                return dbContext;
            }
    
            public static DbContext RefreshAllEntites(this DbContext dbContext, RefreshMode refreshMode)
            {
                return RefreshEntites(dbContext: dbContext, refreshMode: refreshMode, entityType: null); //null entityType is a wild card
            }
    
            public static DbContext RefreshEntites<TEntity>(this DbContext dbContext, RefreshMode refreshMode)
            {
                return RefreshEntites(dbContext: dbContext, refreshMode: refreshMode, entityType: typeof(TEntity));
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      我在数据库中插入后有一个触发器,并且我在一个事务中工作,所以我需要在相同的上下文中获取触发器生成的新值。这对我有用:

      using (var ctx = new context())
      {
          ctx.Connection.Open();
          ctx.Transaction = ctx.Connection.BeginTransaction();
      
          ctx.Entities.InsertOnSubmit(itemDB);
          ctx.SubmitChanges();
          ctx.Refresh(RefreshMode.OverwriteCurrentValues, itemDB);
      
          Model newModel = itemDB.ToModel();
      
          ctx.Transaction.Commit();
          return newModel;
      }
      catch (Exception ex)
      {
          ctx.Transaction.Rollback();
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-10
        • 1970-01-01
        • 2020-07-21
        • 2020-03-15
        • 2013-04-13
        • 1970-01-01
        相关资源
        最近更新 更多