entity-framework - update - save entity framework c#
DbContext AutoDetectChangesEnabled establecido en detección de cambios falsos (3)
Establecer AutoDetectChangesEnabled
en false
no deshabilita el seguimiento de cambios. (Eso es lo que AsNoTracking()
método de extensión AsNoTracking()
). Simplemente deshabilita la llamada automática de DetectChanges
que de otro modo se produciría en muchos métodos de la 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 las entidades rastreados están incompletos o son incorrectos, lo que lleva a que los datos guarden incorrectamente.
En su caso, se espera el estado Added
en la primera parte de su method
, incluso con AutoDetectChangesEnabled
establecido en false
porque solo llama a 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 convertirá un estado incorrecto en un estado correcto, 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 de 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 la propiedad modificada no se guarda en la base de datos.
En la última sección que menciona el estado Unchanged
me estoy refiriendo a mi propia prueba (y también a lo que esperaría). No sé y no puedo reproducir por qué tiene el estado Modified
.
Lo siento, si esto suena un poco confuso. Arthur Vickers puede explicarlo mejor.
Encuentro que la detección automática de cambios y el comportamiento al deshabilitarla son bastante difíciles de entender y de dominar, y generalmente no toco el valor predeterminado ( AutoDetectChangesEnabled
= true
) para los cambios rastreados que son más complejos que los más simples (como las entidades de adición masiva en un bucle, etc.).
Estoy un poco perplejo. Por lo que he leído, configurar DbContext.AutoDetectChangesEnabled
en false
debería deshabilitar el seguimiento de cambios que requiere que uno llame a DbContext.DetectChanges
para identificar los cambios que se enviarán a la base de datos.
Sin embargo, de mis registros a continuación se desprende que los cambios están siendo registrados por dbContexts change tracker, incluso con la configuración establecida en falso.
¿Me estoy perdiendo de 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 registro
***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
Si alguien está buscando AutoDetectChangesEnabled
en Entity Framework Core, puede encontrarlo en ChangeTracker
en ChangeTracker
de Configuration
Uso como:
context.ChangeTracker.AutoDetectChangesEnabled = false;
//Do something here
context.PriceRecords.Add(newPriceRecord);
context.ChangeTracker.AutoDetectChangesEnabled = true;
según el artículo de Entity Framework Automatic Detect Changes
ellos dijeron:
puede obtener mejoras de rendimiento significativas apagándolo 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 hubieran producido al llamar a los métodos DbSet.Add
y SaveChanges
.