it-swarm.com.de

DbContext AutoDetectChangesEnabled wurde auf falsches Erkennen von Änderungen festgelegt

Ich bin ein bisschen ratlos. Nach dem, was ich gelesen habe, sollte das Setzen von DbContext.AutoDetectChangesEnabled Auf false die Änderungsnachverfolgung deaktivieren, wobei ein Aufruf von DbContext.DetectChanges Erforderlich ist, um Änderungen zu identifizieren, die an die Datenbank gesendet werden sollen.

Aus den nachstehenden Protokollen geht jedoch hervor, dass die Änderungen von dbContexts change tracker registriert werden, auch wenn die Einstellung auf false festgelegt ist.

Vermisse ich etwas?

Entity Framework Version: 5.0.0.0

DbContext-Klasse

public class ProjectContext : DbContext {
    public DbSet<Project> Projects {get;set;}
}

Controller-Klasse

private ProjectContext db = new ProjectContext();

public method(){
    Project p = new Project("uniqueName");
    db.Configuration.AutoDetectChangesEnabled = false;
    db.Projects.Add(p);
    DebugChangeTracker();
    db.SaveChanges();

    db.Projects.First().ProjectName = "a differentName!";
    DebugChangeTracker();
    db.SaveChanges();
}

Protokollierungsmethode

    private void DebugChangeTracker()
    {
        var path = "C:\\mypath\\";
        path = path + Util.GetMsSinceEpoch().ToString() + "changeTracker.log";

        using (StreamWriter sw = new StreamWriter(path))
        {
            var changeTracker = db.ChangeTracker;
            var entries = changeTracker.Entries();
            foreach (var x in entries)
            {

                var name = x.Entity.ToString();
                var state = x.State;

                sw.WriteLine("");
                sw.WriteLine("***Entity Name: " + name +
                             "is in a state of " + state);
                var currentValues = x.CurrentValues;
                sw.WriteLine("***CurrentValues***");
                PrintPropertyValues(currentValues,sw);
                if (state != EntityState.Added)
                {
                    sw.WriteLine("***Original Values***");
                    PrintPropertyValues(x.OriginalValues,sw);
                }
            }
        }
    }

Erstes Protokoll

***Entity Name: Models.Projectis in a state of Added
***CurrentValues***
ProjectId:0
ProjectName:uniqueName

Zweites Protokoll

***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
41
Jesse

Wenn Sie AutoDetectChangesEnabled auf false setzen, wird die Änderungsnachverfolgung nicht deaktiviert. (Das ist, was die AsNoTracking() - Erweiterungsmethode tun würde.) Sie deaktiviert nur den automatischen Aufruf von DetectChanges, der ansonsten in vielen DbContext - API-Methoden auftreten würde.

DetectChanges ist jedoch nicht die einzige Methode, die an der Änderungsnachverfolgung teilnimmt. Wenn Sie es jedoch nicht manuell an den richtigen Stellen aufrufen, an denen es benötigt wird, sind die nachverfolgten Entitätszustände unvollständig oder falsch, was zu falsch gespeicherten Daten führt.

In Ihrem Fall wird der Status Added im ersten Teil Ihres method erwartet, auch wenn AutoDetectChangesEnabled auf false gesetzt ist, da Sie nur db.Projects.Add(p). (Die Zeile fehlt übrigens in Ihrem Code, aber ich vermute, es ist nur ein Kopier- und Einfügefehler.) Das Aufrufen einer Methode aus der DbContext -API verfolgt Änderungen korrekt und die Zustände im Tracker sind korrekt, wenn der Zustand war korrigieren Sie vor dem Aufruf von Add.

Oder mit anderen Worten: Das Aufrufen einer API-Methode wandelt einen korrekten Zustand nicht in einen falschen Zustand um. Aber: Wenn AutoDetectChangesEnabledfalse ist, wird auch kein falscher Zustand in einen korrekten Zustand umgewandelt, was der Fall wäre, wenn AutoDetectChangesEnabledtrue ist.

Im zweiten Teil Ihres method ändern Sie jedoch nur einen POCO-Eigenschaftswert. Nach diesem Zeitpunkt ist der Status des Änderungsverfolgers falsch (Unchanged) und ohne Aufruf von DetectChanges (manuell oder - wenn AutoDetectChangesEnabledtrue ist - automatisch in ChangeTracker.Entries oder SaveChanges) wird niemals angepasst. Dies hat zur Folge, dass der geänderte Eigenschaftswert nicht in der Datenbank gespeichert wird.

Im letzten Abschnitt, in dem der Status Unchanged erwähnt wird, beziehe ich mich auf meinen eigenen Test (und auch auf das, was ich erwarten würde). Ich weiß nicht und kann nicht reproduzieren, warum Sie den Status Modified haben.

Sorry, wenn das alles etwas verwirrend klingt. Arthur Vickers kann es besser erklären.

Ich finde die automatische Änderungserkennung und das Verhalten beim Deaktivieren ziemlich schwer zu verstehen und zu beherrschen, und ich berühre normalerweise nicht die Standardeinstellung (AutoDetectChangesEnabled = true) für nachverfolgte Änderungen, die komplexer sind als die einfachsten Dinge (wie Bulk-Hinzufügen von Entitäten in einer Schleife, etc.).

54
Slauma

Wenn jemand nach AutoDetectChangesEnabled in Entity Framework Core sucht, finden Sie es unter ChangeTracker insted von Configuration

Verwendung wie:

context.ChangeTracker.AutoDetectChangesEnabled = false;

//Do something here
context.PriceRecords.Add(newPriceRecord);

context.ChangeTracker.AutoDetectChangesEnabled = true;
9
Jiri Houzvicka

gemäß Entität Artikel von Framework Automatic Detect Changes

sie sagten:

sie können signifikante Leistungsverbesserungen erzielen, indem Sie es in some cases

schauen Sie sich dieses Beispiel aus diesem Artikel an

using (var context = new BloggingContext()) 
{ 
    try 
    { 
        context.Configuration.AutoDetectChangesEnabled = false; 

        // Make many calls in a loop 
        foreach (var blog in aLotOfBlogs) 
        { 
            context.Blogs.Add(blog); 
        } 
    } 
    finally 
    { 
        context.Configuration.AutoDetectChangesEnabled = true; 
    }
}

Dieser Code vermeidet unnötige Aufrufe von DetectChanges, die beim Aufrufen der Methoden DbSet.Add Und SaveChanges aufgetreten wären.

5