webentwicklung-frage-antwort-db.com.de

So aktualisieren Sie DbContext

Ich möchte alle Entitäten meines DbContext aktualisieren, ohne sie neu zu erstellen. Ich habe Folgendes versucht, und keine davon ergibt einen Sinn:

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();

Und der einzige, der mein DbContext auffrischt:

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

Aber es ist zu langsam. Können Sie mir bei der Auswahl des richtigen Weges helfen?

21
Mohsen

Ich habe gerade festgestellt, dass das Ergebnis Enumerable ausgewertet werden sollte, da die Methode Refresh es als Objekt abruft und nicht auswertet.

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);

nd ich bevorzuge folgendes:

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

Ich habe das überprüft und es funktioniert gut:

//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);

Sind Sie sicher, dass es sich um denselben DB-Kontext handelt?

13
yonexbat

In einigen Fällen kann es vorkommen, dass eine Sammlung, die von einer Drittanbieter-App aktualisiert wurde, beim Aktualisieren des Sammlungsobjekts nicht neu geladen wird.

Ich hatte den Fall, dass ich ein Objekt A mit einem Eins-zu-Viele-Verhältnis zu einem Objekt B hatte.

Anwendung 1 lädt ein Objekt A, wobei A.ListB leer ist. Anwendung 2 füllt die A.ListB-Auflistung. Anwendung 1 lädt das Objekt A neu.

Mit der obigen Lösung bleibt A.ListB leer. Ich musste die Sammlung A.ListB explizit neu laden.

Hier ist eine allgemeine Methode, um alle Sammlungen neu zu laden:

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);
}
3
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));
        }
    }
}
3
Sean M

Ich hatte nach dem Einfügen in die Datenbank einen Auslöser und arbeitete in einer Transaktion. Daher musste ich die vom Auslöser generierten neuen Werte im selben Kontext abrufen. Das hat bei mir funktioniert:

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();
}

1