System.ObjectDisposedException: l'instance ObjectContext a été supprimée et ne peut plus être utilisée pour des opérations nécessitant une connexion.
J'utilise EF 4 pour récupérer une liste d'employés.
public ContentResult AutoCompleteResult(string searchText)
{
List<Employee> list = Employee.GetAllCurrentEmployees();
List<Employee> filteredEmployees = list
.Where(x => x.GetName().ToLower().Contains(searchText.ToLower()))
.ToList();
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
var jsonString = jsonSerializer.Serialize(filteredEmployees).ToString();
return Content(jsonString);
}
La liste est récupérée correctement, mais lorsque je la sérialise, je reçois cette exception.
System.ObjectDisposedException: The ObjectContext instance has been
disposed and can no longer be used for
operations that require a connection.
Generated: Wed, 17 Nov 2010 16:06:56 GMT
System.ObjectDisposedException: The ObjectContext instance has been
disposed and can no longer be used for operations that require a connection.
at
System.Data.Objects.ObjectContext.EnsureConnection()
at
System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) at
System.Data.Objects.ObjectQuery`1.Execute(MergeOption mergeOption) at
System.Data.Objects.DataClasses.EntityCollection`1.Load(List`1 collection, MergeOption mergeOption) at
System.Data.Objects.DataClasses.EntityCollection`1.Load(MergeOption mergeOption) at
System.Data.Objects.DataClasses.RelatedEnd.Load() at
System.Data.Objects.DataClasses.RelatedEnd.DeferredLoad() at
System.Data.Objects.DataClasses.EntityCollection`1.System.Collections.IEnumerable.GetEnumerator() at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object
o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse,
SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object
o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat
serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object
obj, StringBuilder output, SerializationFormat serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object
obj, SerializationFormat serializationFormat) at
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj) at
SHP.Controllers.EmployeeController.AutoCompleteResult(String searchText) in C:\Documents and Settings\geoffreypayne\My Documents\Visual Studio
2010\Projects\MVC\SHP\SHP\Controllers\EmployeeController.cs:line
623 at lambda_method(Closure , ControllerBase , Object[] ) at
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext
controllerContext, IDictionary`2 parameters) at
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext
controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) at
System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.InvokeActionMethodWithFilters>b__a()
at
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter
filter, ActionExecutingContext preContext, Func`1 continuation)
at
System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<>c__DisplayClassf.<InvokeActionMethodWithFilters>b__c() at
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) at
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext
controllerContext, String actionName)
Je trouve cela très étrange. J'ai déjà récupéré la liste des employés et le DataContext a été supprimé. Alors, pourquoi aurais-je cette erreur?
Il semble que vous ayez des propriétés de relation paresseuses qui ne l’ont pas encore été (ce qui pose un problème de performance "n + 1" associé). Vous pouvez essayer chargement impatient pour voir si cela aide; sinon, chargez explicitement les données pour chaque élément de la liste, avant, vous fermez le contexte d'objet.
Vous pouvez désactiver le chargement paresseux pour résoudre ce problème.
Dans votre bloc 'using', essayez ceci:
yourObjectContext.ContextOptions.LazyLoadingEnabled = false;
Après cela, j'ai pu sérialiser mon POCO en JSON EF (généré par DbContext) sans aucun problème.
* Remarque: Depuis que j'ai désactivé le chargement différé ..., j'inscris explicitement les objets connexes dont j'ai besoin à l'avance (principalement avec .Include () dans ma requête) avant que l'objet ne soit sérialisé en JSON.
Je pensais que j'allais entrer ici avec mes 2 centimes. Nous avions une très grande couche d'accès aux données, et l'un des programmeurs était habitué à utiliser une instruction using pour le contexte, comme ceci:
using (EntityModel myContext = EntityConnection)
{
//code in here to grab data
}
Nous utilisons EntityConnection en tant que propriété statique servant un dbContext par HttpContext actuel. Toute méthode appelée après son bloc using lèverait l'exception 'l'instance d'ObjectContext a été supprimée' car il était évident que le contexte avait été supprimé après son appel de méthode. Ainsi, si vous n'utilisez qu'un seul contexte d'entité par HttpContext, veillez à ne pas autoriser le récupérateur de place à le supprimer à l'aide d'un bloc using.
J'ai pensé que je mettrais cela dans les réponses car je sais que beaucoup de gens utilisent le contexte de l'entité différemment et que je vois beaucoup utiliser des blocs dans les exemples de code.
Je préfère charger une instance fat déclarée en dehors de l'utilisation
Customer _custObj;
using (RazorOne rz1 = new RazorOne())
{
_custObj = rz1.Customers.FirstOrDefault(); // .Include = Lazy loading
// Versus Implicit Load
_custObj.AddressReference.Load();
_custObj.Address1Reference.Load();
}
Ensuite, je peux la transmettre à la vue ou à l’assistant qui la voulait vraiment.
J'ai eu le même problème et je pouvais le résoudre en sélectionnant une projection de l'objet avec uniquement les propriétés requises par l'appelant, au lieu de renvoyer l'objet complet . Il semble que lorsque vous avez plusieurs relations dans votre objet, le sérialiseur pour naviguer ceux-ci.
Donc, (en supposant que votre contexte d'objet s'appelle "Entities"), je voudrais essayer quelque chose comme ceci:
using ( Entities context = new Entities() )
{
var employeeProjection = (from e in context.Employee
select new { e.Id, c.FirstName, e.LastName }).ToList();
return employeeProjection;
}
Cela ressemble à une évaluation paresseuse ou retardée; vous ne pouvez pas supposer que les objets sont "chargés" jusqu'à ce que vous essayiez réellement de les lire.
Vous devez conserver votre DataContext
jusqu'à ce que vous ayez complètement fini de manipuler les objets extraits de la base de données pour éviter ces erreurs.
J'ai trouvé le meilleur moyen de gérer cela et de conserver la déclaration using dont vous avez juste besoin d'utiliser include, voir l'exemple ci-dessous:
using (var ctx = new Context(this.connectionString)) {
var query = ctx.[maintable]
.Include(x => x.[theothertable])
.FirstOrDefaultAsync(u => u.UserName.Equals(userName));
}
J'ai eu une variation sur ce problème. Le contexte de données n'a pas été fermé, mais l'instance de contexte d'objet a été supprimée. Une erreur a néanmoins été générée.
Il s'est avéré que l'objet avait une clé étrangère auto-référentielle (c'est-à-dire la clé étrangère renvoyée dans la même table). En accédant à la propriété de navigation dans le cas où elle fait référence à un null, vous obtenez une exception disposée par objectcontext au lieu, par exemple, d’une exception de pointeur null.
par exemple:
var a = myObject.Name; // works because myObject still has open object context
var b = myObject.SelfReference; // throws objectcontext disposed if SelfReference is null
using (EmployeeContext db= new EmployeeContext())
{
var lst = db.Employees.Select(p=> new {
EmployeeID = p.EmployeeID,
Name = p.Name,
Salary = p.Salary,
Position = p.Position,
Age = p.Age,
Office = p.Office
}).ToList();
return Json(lst, JsonRequestBehavior.AllowGet);
}
Je me permets d’examiner votre objet Employé et de vous assurer que votre mot-clé n’est pas virtuel. Le mot clé virtual est interprété par Entity Framework comme "lazy-load". Nous aurions besoin de voir votre classe Employé pour affirmer de manière absolue pourquoi vous pourriez voir l'exception.