web-dev-qa-db-fra.com

La nouvelle transaction n'est pas autorisée car d'autres threads s'exécutent dans la session LINQ To Entity

Des idées sur pourquoi cela pourrait se casser?

foreach (var p in pp)
{
    ProjectFiles projectFile = (ProjectFiles)p;
    projectFile.Status = Constants.ProjectFiles_ERROR;
    projectFile.DateLastUpdated = DateTime.Now;
    context.SaveChanges();
}

J'ai lu que la solution de rechange au problème consiste à récupérer les résultats en une fois avant la boucle foreach.

Mais n'ai-je pas fait ça? "pp" est la collection de résultats dans mon cas

137
Nick LaMarca

La variable pp n'est pas une collection d'objets, c'est un énumérateur qui peut renvoyer des objets. Pendant que vous utilisez l'énumérateur, la source doit rester ouverte.

Utilisez la méthode ToList pour réaliser l’énumérateur dans une collection. Cela lira tous les éléments de l'énumérateur et fermera la connexion à la source, de sorte que vous pourrez utiliser la connexion pour autre chose.

foreach (var p in pp.ToList())
353
Guffa

En réalité, vous utilisez une connexion SQL pour parcourir une collection d'entités de base de données, puis vous utilisez une autre connexion pour enregistrer les modifications. Cela se produit parce que vos classes sont fondamentalement "mariées" à une instance de votre connexion à la base de données et ne peuvent pas être modifiées par une autre.

Une façon de contourner ce problème consiste à appeler .ToList() sur votre collection avant de l'itérer.

Et pendant que vous y êtes, appelez context.SaveChanges() une seule fois après la fin de la boucle pour accélérer le code.

9
Captain Kenpachi