C# 如何刷新 DbContext
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18169970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Refresh DbContext
提问by Mohsen
I want to refresh all entities of my DbContext
without recreating it, I tried the following and none of them make sense:
我想在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();
And the only one which refreshes my DbContext
:
唯一一个刷新我的DbContext
:
foreach (var i in this.Orm.ChangeTracker.Entries())
i.Reload();
But it's too slow. Can you help me choosing the right way?
但它太慢了。你能帮我选择正确的方式吗?
采纳答案by Mohsen
I just found that the Enumerable
result should be evaluated because the Refresh
method gets it as object and doesn't evaluate it.
我刚刚发现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);
And I prefer the following:
我更喜欢以下内容:
var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c=>c.Entity).ToList();
context.Refresh(RefreshMode.StoreWins, refreshableObjects);
回答by yonexbat
I checked this and id works fine:
我检查了这个,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);
Are you sure it is the same db-context?
你确定它是相同的数据库上下文吗?
回答by Sean M
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));
}
}
}
回答by Anthony Brenelière
In some cases, if a collection has been updated by a third party app, the collection may not be reloaded when refreshing the collection's object.
在某些情况下,如果某个集合已被第三方应用程序更新,则在刷新该集合的对象时可能不会重新加载该集合。
I had the case where I had an object A with a one to many relashionship to an object B.
我遇到过这样的情况,我有一个对象 A 与对象 B 有一对多的关系。
Application 1 loads an object A with A.ListB empty. Application 2 fills the A.ListB collection. Application 1 reloads the object A.
应用程序 1 加载一个对象 A,其中 A.ListB 为空。应用程序 2 填充 A.ListB 集合。应用程序 1 重新加载对象 A。
With the solution above, A.ListB remains empty. I had to reload the collection A.ListB explicitly.
使用上述解决方案,A.ListB 保持为空。我不得不显式地重新加载集合 A.ListB。
Here is a generic way to have all collections reloaded:
这是重新加载所有集合的通用方法:
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);
}
回答by Cristinadeveloper
I had a trigger after insert in the database and I was working inside a transaction, so I needed to get the new values generated by the trigger in the same context. This worked for me:
我在数据库中插入后有一个触发器并且我在事务中工作,所以我需要在相同的上下文中获取触发器生成的新值。这对我有用:
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();
}