DbContext AutoDetectChangesEnabled set to false detecting changes
Estoy un poco perplejo. Por lo que he leído configurar DbContext.AutoDetectChangesEnabled
a false
debería desactivar el seguimiento de cambios que requiere llamar a DbContext.DetectChanges
para identificar los cambios que se enviarán a la base de datos.
Sin embargo, está claro a partir de mis registros a continuación que los cambios están siendo registrados por DbContexts change tracker, incluso con la configuración establecida en false.
¿Me estoy perdiendo algo?
Versión de Entity Framework: 5.0.0.0
Clase DbContext
public class ProjectContext : DbContext {
public DbSet<Project> Projects {get;set;}
}
Clase de controlador
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étodo de registro
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);
}
}
}
}
Primer registro
***Entity Name: Models.Projectis in a state of Added
***CurrentValues***
ProjectId:0
ProjectName:uniqueName
Segundo Log
***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
3 answers
Establecer AutoDetectChangesEnabled
a false
no deshabilita el seguimiento de cambios. (Eso es lo que haría el método de extensión AsNoTracking()
.) Solo deshabilita la llamada automática de DetectChanges
que de otra manera ocurriría en muchos métodos API DbContext
.
Pero DetectChanges
no es el único método que participa en el seguimiento de cambios. Sin embargo, si no lo llama manualmente en los lugares correctos donde se necesita, los estados de entidad rastreados están incompletos o son incorrectos, lo que conduce a datos guardados incorrectamente.
En su caso, el estado Added
en la primera parte de su method
se espera, incluso con AutoDetectChangesEnabled
establecido en false
porque solo llama db.Projects.Add(p)
. (La línea falta en su código por cierto, pero supongo que es solo un error de copiar y pegar.) Llamar a un método desde la API DbContext
rastrea los cambios correctamente y los estados en el rastreador serán correctos si el estado era correcto antes de la llamada a Add
.
O en otras palabras: Llamar a un método API no convierte un estado correcto en un estado incorrecto. Pero: Si AutoDetectChangesEnabled
es false
tampoco lo hará convertir un estado incorrecto en un estado correcto, lo que sería el caso si AutoDetectChangesEnabled
es true
.
Sin embargo, en la segunda parte de su method
solo está cambiando un valor de propiedad POCO. Después de este punto, el estado del rastreador de cambios es incorrecto (Unchanged
) y sin una llamada a DetectChanges
(manualmente o - si AutoDetectChangesEnabled
es true
- automáticamente en ChangeTracker.Entries
o SaveChanges
) nunca se ajustará. El efecto es que el valor de propiedad cambiado no se guarda en la base de datos.
En la última sección mencionando la estado Unchanged
Me estoy refiriendo a mi propia prueba (y también a lo que esperaría). No lo sé y no puedo reproducir por qué tienes estado Modified
.
Lo siento, si esto suena todo un poco confuso. Arthur Vickers puede explicarlo mejor.
Encuentro la detección automática de cambios y el comportamiento al deshabilitarlo bastante difícil de entender y dominar y generalmente no toco el valor predeterminado (AutoDetectChangesEnabled
= true
) para cualquier cambio rastreado que sea más complejo que las cosas más simples (como la adición masiva de entidades en un bucle, etc.).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-31 20:39:40
De acuerdo con Entity Framework Automatic Detect Changes's Article
Dijeron:
Puede obtener mejoras significativas en el rendimiento si lo desactiva en
some cases
Mira este ejemplo de ese artículo
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;
}
}
Este código evita llamadas innecesarias a DetectChanges
que se habrían producido al llamar a los métodos DbSet.Add
y SaveChanges
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 09:52:54
Si alguien busca AutoDetectChangesEnabled
en Entity Framework Core, lo puede encontrar en ChangeTracker
insted de Configuration
Uso como:
context.ChangeTracker.AutoDetectChangesEnabled = false;
//Do something here
context.PriceRecords.Add(newPriceRecord);
context.ChangeTracker.AutoDetectChangesEnabled = true;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-27 09:44:12