stored pattern framework c# asp.net-mvc entity-framework catch-all

c# - pattern - Entity Framework Caching Issue



entity framework vs stored procedures (10)

Cuando usa EF, carga de manera predeterminada cada entidad solo una vez por contexto. La primera consulta crea instancia de entidad y la almacena internamente. Cualquier consulta posterior que requiera entidad con la misma clave devuelve esta instancia almacenada. Si los valores en el almacén de datos cambiaron, aún recibirá la entidad con los valores de la consulta inicial

Una respuesta cuidadosa:

https://stackoverflow.com/a/3653392/1863179

Soy nuevo en Entity Framework.

Tengo algunos valores en mi base de datos usando EF. Devuelve perfectamente, y los valores se muestran en etiquetas. Pero cuando elimino todos los valores en mi tabla (sin usar EF), la consulta EF devuelve mis valores anteriores. Sé que EF almacena los valores en caché y devuelve los datos almacenados en caché para ejecuciones posteriores. ¿Es esto correcto?

Entonces, ¿cómo puedo resolver el problema cuando eliminé todos los valores en mi base de datos, pero EF devuelve los valores anteriores?

Editar :

Ahora utilicé datamodel.SaveChanges() . Pero ahora devuelve los mismos valores antiguos.

Mi consulta de muestra se ve a continuación:

SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities(); datamodel.SaveChanges(); List<Compliance> compliance=new List<Compliance>(); IList<ComplianceModel> complianceModel; if (HttpContext.Current.User.IsInRole("SuperAdmin")) { compliance = datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList(); }


Creo que debería seguir algunas de las otras soluciones aquí, pero parece que quiere borrar el caché. Puedes lograr esto haciendo lo siguiente:

var count = datamodel.Compliances.Local.Count; // number of items in cache (ex. 30) datamodel.Compliances.Local.ToList().ForEach(c => { datamodel.Entry(c).State = EntityState.Detached; }); count = datamodel.Compliances.Local.Count; // 0


Creo que lo que necesitas es GetDatabaseValues() . Se usa como:

context.Entry(/*your entry*/).GetDatabaseValues();

La siguiente información es de msdn :

Los valores actuales son los valores que las propiedades de la entidad contienen actualmente. Los valores originales son los valores que se leyeron de la base de datos cuando se consultó a la entidad. Los valores de la base de datos son los valores tal como están almacenados actualmente en la base de datos. Obtener los valores de la base de datos es útil cuando los valores en la base de datos pueden haber cambiado desde que se consultó a la entidad, como cuando otro usuario ha realizado una edición simultánea de la base de datos.


EF no cargará los cambios a menos que vuelva a consultar el contexto. EF consulta db y cargas los mapea en objetos, observa los cambios que realiza en objetos y no en la base de datos. EF no realiza un seguimiento de los cambios realizados directamente en la base de datos y nunca hará un seguimiento.

Ha cargado una Lista, esa Lista es su caché en la memoria. Incluso al llamar Guardar cambios no se actualizará. Tendrá que consultar el contexto una vez más, es decir, crear una nueva lista.

Para ver los cambios Tendrá que ejecutar la siguiente línea una vez más,

datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList()


El siguiente código ayudó a refrescar mi objeto con nuevos valores de base de datos. El comando Entry (object) .Reload () fuerza al objeto a recuperar los valores de la base de datos

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName); DatabaseObjectContext.Entry(member).Reload();


En primer lugar, no recomendaría modificar la base de datos externa a su sistema a menos que solo esté realizando pruebas y desarrollos.

EF DbContext contiene una interfaz IDisposable. Para liberar cualquier información almacenada en caché, realice las llamadas a Dispose manualmente o coloque su Objeto de Base de Datos dentro de un bloque de uso.

using (SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities()) { List<Compliance> compliance = new List<Compliance>(); IList<ComplianceModel> complianceModel; if (HttpContext.Current.User.IsInRole("SuperAdmin")) { compliance = datamodel.Compliances.Where(c => c.School.DistrictId == districtId).ToList(); } }

Esto asegurará que el contexto se borre y recree la próxima vez que se use. Asegúrese de hacer esto para todas sus llamadas y no solo con las que tiene problemas.


Junte cosas que puede hacer.

  1. Use un nuevo contexto. Las entidades en caché se almacenan en el contexto. Usar un nuevo contexto evita que use el caché.
  2. Si realmente desea un contexto global / de larga duración, tiene dos subopciones: a) siempre llame al método Recargar. db.Entry (entidad) .Reload () ... esto fuerza al contexto a recargar esa entidad. b.) utilice un objeto SqlDependency para detectar cuándo los registros cambian y vuelven a cargar las entidades según sea necesario. https://code.msdn.microsoft.com/How-to-use-SqlDependency-5c0da0b3

Si sabe que los cambios ocurrieron fuera de EF y desea actualizar su ctxt para una entidad específica, puede llamar a ObjectContext.Refresh

datamodel.Refresh(RefreshMode.StoreWins, orders);

Si parece que esto será una ocurrencia común, debe deshabilitar el almacenamiento en memoria caché de objetos en sus consultas:

SchoolBriefcaseEntities datamodel = new SchoolBriefcaseEntities(); datamodel.tblCities.MergeOption = MergeOption.NoTracking;

o para desactivar el almacenamiento en caché de nivel de objeto para una entidad específica,

Context.Set<Compliances>().AsNoTracking();


Sospecho que el problema subyacente aquí es que su DbContext está dando vueltas por mucho tiempo. Puedo decir por el hecho de que está utilizando HttpContext que tiene una aplicación web, y las pautas generales cuando se trabaja con DbContext incluyen

Cuando trabaje con aplicaciones web, use una instancia de contexto por solicitud.

Si está utilizando MVC, puede usar el patrón Dispose en su controlador de esta manera:

public class EmployeeController : Controller { private EmployeeContext _context; public EmployeeController() { _context = new EmployeeContext(); } public ActionResult Index() { return View(_context.Employees.ToList()); } protected override void Dispose(bool disposing) { if (disposing) { _context.Dispose(); } base.Dispose(disposing); } }

Pero realmente debería considerar la inyección de dependencia para administrar el ciclo de vida de DbContext


Te recomiendo que utilices alguna MergeOption para todas las EntitieSet después de crear el contexto, así:

var objSetProps = ctx.GetType().GetProperties().Where(prop => prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(ObjectSet<>)); foreach (PropertyInfo objSetProp in objSetProps) { ObjectQuery objSet = (ObjectQuery)objSetProp.GetValue(ctx, BindingFlags.GetProperty, null, null, null); objSet.MergeOption = MergeOption.PreserveChanges; }

Lea acerca de MergeOption aquí: http://msdn.microsoft.com/en-us/library/system.data.objects.mergeoption.aspx Tu utilizará NoTracking, creo.

Pero, tú, ¿QUIERES borrar las entidades "en caché", quitándola?

var entidades = Ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged); foreach (var objectStateEntry in entidades) Ctx.Detach(objectStateEntry.Entity);

Donde Ctx es mi contexto.