Entity Framework: Il y a déjà un DataReader ouvert associé à cette Commande
Je suis en utilisant Entity Framework et parfois je reçois ce message d'erreur.
EntityCommandExecutionException
{"There is already an open DataReader associated with this Command which must be closed first."}
at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands...
Même si je ne fais pas n'importe quel manuel de gestion de la connexion.
cette erreur se produit par intermittence.
code qui déclenche l'erreur (raccourci pour faciliter la lecture):
if (critera.FromDate > x) {
t= _tEntitites.T.Where(predicate).ToList();
}
else {
t= new List<T>(_tEntitites.TA.Where(historicPredicate).ToList());
}
à l'aide de modèle dispose afin d'ouvrir une nouvelle connexion à chaque fois.
using (_tEntitites = new TEntities(GetEntityConnection())) {
if (critera.FromDate > x) {
t= _tEntitites.T.Where(predicate).ToList();
}
else {
t= new List<T>(_tEntitites.TA.Where(historicPredicate).ToList());
}
}
toujours problématique
pourquoi ne pas EF réutiliser une connexion s'il est déjà ouvert.
- Je me rends compte que cette question est ancienne, mais je serais curieux de savoir quel est le type de votre
predicate
ethistoricPredicate
variables sont. J'ai découvert que si vous passezFunc<T, bool>
àWhere()
de compiler et parfois de travail (car il ne le "où" à la mémoire). Ce que vous devrait faire, c'est passerExpression<Func<T, bool>>
àWhere()
.
Vous devez vous connecter pour publier un commentaire.
Il n'est pas à propos de la fermeture de la connexion. EF gère la connexion correctement. Ma compréhension de ce problème est qu'il y a plusieurs récupération des données des commandes exécutées sur un seul type de connexion (ou de commande unique avec de multiples sélectionne) tout en suivant DataReader est exécutée avant la première a terminé la lecture. La seule façon d'éviter l'exception est de permettre à de multiples imbriquées DataReaders = tourner sur MultipleActiveResultSets. Un autre scénario lorsque cela arrive toujours, c'est quand vous itérer résultat de la requête (IQueryable) et vous permettra de déclencher le chargement paresseux pour chargé de l'entité à l'intérieur de l'itération.
DbContext
EF) une solution valable?En alternative à l'utilisation de MARS (MultipleActiveResultSets) vous pouvez écrire votre code si vous n'avez pas d'ouvrir plusieurs jeux de résultats.
Ce que vous pouvez faire est de récupérer les données en mémoire, de cette façon, vous n'aurez pas le lecteur ouvert.
Elle est souvent causée par une itération à travers un jeu de résultats en essayant d'ouvrir un autre jeu de résultats.
Exemple De Code:
Permet de dire que vous faites une recherche dans votre base de données contenant ces:
Nous pouvons faire une solution simple à ce problème en ajoutant .ToList() comme ceci:
Cette forces entityframework de charger la liste en mémoire, donc quand nous itération de si elle dans la boucle foreach, il n'est plus en utilisant le lecteur de données pour ouvrir la liste, c'est la place dans la mémoire.
Je me rends compte que cela pourrait ne pas être désiré si vous voulez lazyload certaines propriétés, par exemple.
C'est surtout un exemple qui nous l'espérons vous explique comment/pourquoi, vous pourriez obtenir ce problème, de sorte que vous pouvez prendre des décisions en conséquence
ToList
ing un millier d'objets, il va augmenter la mémoire d'une tonne. Dans cet exemple précis, que vous seriez mieux en combinant la requête interne avec la première de sorte qu'une seule requête est générée au lieu de deux.Il y a une autre façon de surmonter ce problème. Si c'est une bonne solution dépend de votre situation.
Le résultat de ce problème de chargement paresseux, donc une façon de l'éviter est de ne pas avoir de chargement paresseux, grâce à l'utilisation d'Inclure:
Si vous utilisez le
Include
s, vous pouvez éviter l'activation de MARS. Mais si vous manquez une, vous obtiendrez l'erreur, de sorte que l'activation de MARS est probablement le moyen le plus facile de la corriger..Include
est une bien meilleure solution que l'activation de MARS, et beaucoup plus facile que d'écrire votre propre code de requête SQL.Vous obtenez cette erreur, quand la collection que vous essayez d'effectuer une itération est une sorte de lazy loading (IQueriable).
La conversion de la IQueriable collection dans d'autres énumérable collection permettra de résoudre ce problème.
exemple
Note: .ToList() crée un nouvel ensemble de tous les temps, et il peut causer le problème de performances si vous travaillez avec des données de grande taille.
SELECT COUNT(*) FROM Users
= 5J'ai résolu le problème facilement (pragmatique) par l'ajout de l'option pour le constructeur. J'ai donc l'utiliser uniquement lorsque cela est nécessaire.
essayer dans votre chaîne de connexion pour définir "MultipleActiveResultSets=true"
cela permet le multitâche sur la base de données .
"Server=yourserver ;AttachDbFilename=base de données;User Id=sa;Mot de passe=bla ;MultipleActiveResultSets=true;App=EntityFramework"
c'est fonctionne pour moi ... si votre connexion dans l'application.config, ou par programmation ...
espérons que cette utile
J'avais initialement décidé d'utiliser un champ statique dans ma classe de l'API pour faire référence à une instance de MyDataContext objet (Où MyDataContext est un EF5 objet de Contexte), mais c'est ce qui semblait pour créer le problème. J'ai ajouté le code à quelque chose comme à chacun de mes méthodes de l'API et qui a résolu le problème.
Que d'autres personnes ont déclaré, l'EF Contexte de Données les objets ne sont PAS thread-safe. Afin de les placer dans l'objet statique qui peut éventuellement causer le "lecteur de données" erreur dans les bonnes conditions.
Mon hypothèse initiale était que la création d'une seule instance de l'objet serait plus efficace, et permettre une meilleure gestion de la mémoire. De ce que j'ai recueillies à la recherche de cette question, qui n'est pas le cas. En fait, il semble être plus efficace pour traiter chaque appel à votre API comme un cas isolé, thread-safe de l'événement. Veiller à ce que toutes les ressources sont correctement libérée, que l'objet est hors de portée.
Cela a un sens, surtout si vous prenez votre API pour la prochaine progression naturelle qui serait à l'exposer comme un Service web ou une API REST.
Divulgation
J'ai remarqué que cette erreur se produit lors de l'envoi d'un IQueriable de la vue et de l'utiliser dans un double foreach, où l'intérieur foreach doit également utiliser la connexion. Exemple Simple (ViewBag.les parents peuvent être IQueriable ou DbSet):
La solution la plus simple est d'utiliser
.ToList()
sur la collection avant de l'utiliser. Notez également que MARS ne fonctionne pas avec MySQL.ToList()
sur mon premier appel d'obtenir une collection à partir de la DB. Puis j'ai fait uneforeach
sur cette liste et les appels suivants ont fonctionné à la perfection, au lieu de donner l'erreur.Un bon milieu entre l'activation de MARS et de la récupération de la totalité du jeu de résultats dans la mémoire est d'extraire uniquement les Id dans une requête initiale, et ensuite une boucle sur l'Id de matérialiser chaque entité, comme vous allez.
Par exemple (en utilisant le "Blog et les Messages" échantillon entités comme dans cette réponse):
Faire cela signifie que vous tirez de quelques milliers d'entiers en mémoire, par opposition à des milliers de l'ensemble des graphes d'objets, ce qui devrait réduire l'utilisation de la mémoire tout en vous permettant de travailler point par point sans l'activation de MARS.
Une autre belle prestation de cela, comme on le voit dans l'exemple, c'est que vous pouvez enregistrer les modifications que vous en boucle sur chaque élément, au lieu d'avoir à attendre jusqu'à la fin de la boucle (ou tout autre solution de contournement), comme cela serait nécessaire, même avec MARS activé (voir ici et ici).
context.SaveChanges();
à l'intérieur de la boucle 🙁 . Ce n'est pas bon. il doit être à l'extérieur de la boucle.J'ai trouvé que j'ai eu la même erreur, et il s'est produit lorsque j'ai été en utilisant un
Func<TEntity, bool>
au lieu d'unExpression<Func<TEntity, bool>>
pour votrepredicate
.Une fois que j'ai changé tous les
Func's
àExpression's
l'exception cessé d'être jetés.Je crois que
EntityFramwork
n'certaines choses intelligentes avecExpression's
qui elle n'a tout simplement pas le faire avecFunc's
(MyTParent model, Func<MyTChildren, bool> func)
de sorte que mon Viewmodel peut spécifier un certainwhere
clause Générique DataContext de la méthode. Rien ne fonctionnait jusqu'à ce que je l'ai fait.2 solutions pour pallier à ce problème:
.ToList()
après votrede la requête, de sorte que vous pouvez ensuite itérer dessus de l'ouverture d'un nouveau DataReader.
.Include
(/autres entités que vous souhaitez charger dans la requête/) ceest appelé désireux de chargement, ce qui vous permet (en effet) comprennent
associés à des objets(entités) au cours de l'exécution d'une requête avec le
DataReader.
Dans mon cas, j'ai trouvé qu'il manquait des "attendent" des déclarations avant myContext.SaveChangesAsync() appelle. L'ajout d'attendre avant de ces appels asynchrones fixe le lecteur de données de questions pour moi.
Si nous essayons de regrouper une partie de nos conditions de travail dans un Func<> ou l'extension de la méthode, nous allons obtenir cette erreur, supposons que nous avons un code comme ceci:
Ceci lancera l'exception, si nous essayons de l'utiliser dans un cas(), ce que nous devrions faire à la place est de construire un Prédicat comme ceci:
De plus, peut être lu à : http://www.albahari.com/nutshell/predicatebuilder.aspx
Ce problème peut être résolu simplement en convertissant les données d'une liste
Dans ma situation, le problème est survenu à cause d'une injection de dépendance de l'enregistrement. J'ai été à injecter un par demande portée de service qui a été à l'aide d'un dbcontext dans un singleton de service déposée. A cet effet le dbcontext a été utilisé dans plusieurs demande et, partant, de l'erreur.
J'ai résolu ce problème en utilisant la section suivante de code avant la deuxième requête:
vous pouvez modifier le temps de sommeil en millisecondes
P. D. Utile lors de l'utilisation de threads