Je veux rafraîchir toutes les entités de mon DbContext
sans le recréer, j'ai essayé ce qui suit et aucune d'entre elles n'a de sens:
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();
Et le seul qui rafraîchit mon DbContext
:
foreach (var i in this.Orm.ChangeTracker.Entries())
i.Reload();
Mais c'est trop lent. Pouvez-vous m'aider à choisir la bonne façon?
Je viens de découvrir que le résultat Enumerable
doit être évalué car la méthode Refresh
l'obtient en tant qu'objet et ne l'évalue pas.
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);
Et je préfère ce qui suit:
var refreshableObjects = myDbContext.ChangeTracker.Entries().Select(c=>c.Entity).ToList();
context.Refresh(RefreshMode.StoreWins, refreshableObjects);
J'ai vérifié cela et id fonctionne bien:
//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);
Êtes-vous sûr que c'est le même contexte db?
Dans certains cas, si une collection a été mise à jour par une application tierce, la collection peut ne pas être rechargée lors de l'actualisation de l'objet de la collection.
J'ai eu le cas où j'avais un objet A avec une relation un à plusieurs avec un objet B.
L'application 1 charge un objet A avec A.ListB vide. L'application 2 remplit la collection A.ListB. L'application 1 recharge l'objet A.
Avec la solution ci-dessus, A.ListB reste vide. J'ai dû recharger la collection A.ListB explicitement.
Voici une façon générique de recharger toutes les collections:
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);
}
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));
}
}
}
J'avais un déclencheur après l'insertion dans la base de données et je travaillais à l'intérieur d'une transaction, donc j'avais besoin d'obtenir les nouvelles valeurs générées par le déclencheur dans le même contexte. Cela a fonctionné pour moi:
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();
}