关于c#:如何刷新DbContext

How to Refresh DbContext

我想刷新我的DbContext的所有实体而不重新创建它,我尝试了以下操作,但没有一个有意义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

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

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


我只是发现应该对Enumerable结果进行评估,因为Refresh方法将其作为对象获取并且不对其进行评估。

1
2
3
4
5
6
7
8
9
10
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);

我更喜欢以下内容:

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


我检查了一下,id工作正常:

1
2
3
4
5
6
7
8
9
10
11
//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);

您确定它是相同的数据库上下文吗?


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

我遇到的情况是,我的对象A与对象B具有一对多的关系。

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

使用上述解决方案,A.ListB保持为空。我必须显式重新加载集合A.ListB。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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));
        }
    }
}

在数据库中插入后,我有一个触发器,并且正在事务中进行操作,因此我需要在相同的上下文中获取由触发器生成的新值。这为我工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
}