He encontrado lo que parece ser un problema común: estoy actualizando valores en mi base de datos, pero EF está utilizando su copia original en memoria del objeto y estos valores modificados no se reflejan en los datos mostrados. Entiendo por qué es esto, pero no puedo encontrar una manera de evitarlo.¿Cómo desactivo el seguimiento de cambios en el nivel de DbContext en EF 4.1 RC?
La solución más común parece ser MergeOptions.NoTracking
para desactivar por completo el seguimiento de cambios (o usar el método de extensión AsNoTracking()
al realizar consultas) y forzar una actualización cada vez que se accede al objeto, lo que está bien para mis propósitos.
Tengo un repositorio genérico base que mis otros repositorios heredan de:
public abstract class RepositoryBase<T> where T : class
{
private readonly IDbSet<T> _dbset;
private readonly IUnitOfWork _unitOfWork;
protected RepositoryBase(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_dbset = _unitOfWork.Database.Set<T>();
}
public virtual IQueryable<T> All()
{
return _dbset;
}
// Some other IQueryable methods here (Query, GetByProductCode etc)
public virtual T Get(long id)
{
return _dbset.Find(id);
}
}
Y un DbContext
así:
public class Db : DbContext
{
private IDbSet<Product> _products;
public IDbSet<Product> Products
{
get { return _products ?? (_products = DbSet<Product>()); }
}
public virtual IDbSet<T> DbSet<T>() where T : class
{
return Set<T>();
}
public virtual void Commit()
{
base.SaveChanges();
}
}
Si cambio el método de mi repositorio All()
así:
public virtual IQueryable<T> All()
{
return _dbset.AsNoTracking();
}
obtengo el resultado deseado - una actualización en la base de datos se refleja cuando la página que muestra los productos se actualiza. Sin embargo, no puedo hacer esto en el método Get()
, ya que ese método de extensión solo funciona en un IQueryable
.
Idealmente me gustaría desactivar esta opción en el nivel DbContext
ya que nunca necesitará cambiar de seguimiento, pero no parece ser una manera obvia de hacerlo, y no hay casi cero la documentación sobre el tema (a menos que alguien me pueda indicar algo? ¡Por favor!).
He intentado añadir un constructor para la DbContext
con estas opciones de configuración desactivada:
public Db()
{
base.Configuration.ProxyCreationEnabled = false;
base.Configuration.AutoDetectChangesEnabled = false;
}
pero tengo que admitir que sólo supongo que lo que realmente hacen (que sólo los encontré a través de mirar en la fuente código), y no parecen tener ningún efecto de todos modos.
Cualquier ayuda sería muy apreciada. Si más información/código ayudaría, házmelo saber.
Gracias por la respuesta. Pensé que * estaba * creando un nuevo contexto por solicitud, pero debido a lo que has señalado aquí, sospecho que podría tener algo mal configurado en la configuración de mi Ninject ... ¡Lo revisaré mañana y volveré a informar! –
Parece que este es el problema. No estoy creando un nuevo DbContext por solicitud, o más bien, Ninject no lo es, aunque he especificado 'InRequestScope()' en la inyección. Creo que ahora es una pregunta aparte, pero gracias por su ayuda para llegar tan lejos. –
He aceptado esta respuesta a pesar de que * no * responde * directamente a la pregunta, porque me llevó a una solución. –