Je suis un peu perplexe. D'après ce que j'ai lu en définissant le DbContext.AutoDetectChangesEnabled
à false
devrait désactiver le suivi des modifications nécessitant un appel à DbContext.DetectChanges
afin d'identifier les modifications à envoyer à la base de données.
Cependant, il ressort clairement de mes journaux ci-dessous que les modifications sont enregistrées par dbContexts change tracker, même avec le paramètre défini sur false.
Suis-je en train de manquer quelque chose?
Version d'Entity Framework: 5.0.0.0
Classe DbContext
public class ProjectContext : DbContext {
public DbSet<Project> Projects {get;set;}
}
Classe de contrôleur
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();
}
Méthode d'enregistrement
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);
}
}
}
}
Premier journal
***Entity Name: Models.Projectis in a state of Added
***CurrentValues***
ProjectId:0
ProjectName:uniqueName
Deuxième journal
***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
La définition de AutoDetectChangesEnabled
sur false
ne désactive pas le suivi des modifications. (C'est ce que ferait la méthode d'extension AsNoTracking()
.) Elle désactive simplement l'appel automatique de DetectChanges
qui se produirait autrement dans de nombreuses méthodes d'API DbContext
.
Mais DetectChanges
n'est pas la seule méthode qui participe au suivi des modifications. Cependant, si vous ne l'appelez pas manuellement aux bons endroits où cela est nécessaire, les états des entités suivies sont incomplets ou incorrects, ce qui entraîne des données incorrectement enregistrées.
Dans votre cas, l'état Added
dans la première partie de votre method
est attendu, même avec AutoDetectChangesEnabled
défini sur false
car vous n'appelez que db.Projects.Add(p)
. (La ligne est manquante dans votre code btw, mais je suppose que c'est juste une erreur de copier-coller.) L'appel d'une méthode à partir de l'API DbContext
suit correctement les changements et les états du tracker seront corrects si l'état correct avant l'appel à Add
.
Ou en d'autres termes: l'appel d'une méthode API ne transforme pas un état correct en un mauvais état. Mais: si AutoDetectChangesEnabled
est false
, cela ne transformera pas non plus un mauvais état en un état correct, ce qui serait le cas si AutoDetectChangesEnabled
est true
.
Cependant, dans la deuxième partie de votre method
, vous modifiez simplement une valeur de propriété POCO. Après ce point, l'état du suivi des modifications est incorrect (Unchanged
) et sans appel à DetectChanges
(manuellement ou - si AutoDetectChangesEnabled
est true
- automatiquement dans ChangeTracker.Entries
ou SaveChanges
) il ne sera jamais ajusté. L'effet est que la valeur de propriété modifiée n'est pas enregistrée dans la base de données.
Dans la dernière section mentionnant l'état Unchanged
je me réfère à mon propre test (et aussi à ce que j'attendrais). Je ne sais pas et ne peux pas reproduire pourquoi vous avez l'état Modified
.
Désolé, si cela vous semble un peu déroutant. Arthur Vickers peut mieux l'expliquer.
Je trouve la détection automatique des modifications et le comportement lors de la désactivation plutôt difficiles à comprendre et à maîtriser et je ne touche généralement pas la valeur par défaut (AutoDetectChangesEnabled
= true
) pour les modifications suivies qui sont plus complexes que les choses les plus simples (comme l'ajout en masse d'entités dans une boucle, etc.).
Si quelqu'un recherche AutoDetectChangesEnabled
dans Entity Framework Core, vous pouvez le trouver sous ChangeTracker
insted de Configuration
Utilisation comme:
context.ChangeTracker.AutoDetectChangesEnabled = false;
//Do something here
context.PriceRecords.Add(newPriceRecord);
context.ChangeTracker.AutoDetectChangesEnabled = true;
selon l'entité article de Framework Automatic Detect Changes
ils ont dit:
vous pouvez obtenir des améliorations significatives des performances en le désactivant dans
some cases
regardez cet exemple de cet article
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;
}
}
Ce code évite les appels inutiles à DetectChanges
qui se seraient produits lors de l'appel de DbSet.Add
et SaveChanges
méthodes.