248 votes

Entity Framework Core: une deuxième opération a été lancée dans ce contexte avant la fin d'une opération précédente.

Je suis en train de travailler sur un ASP.Net Core 2.0 projet à l'aide de Entity Framework Core

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0"/>

Et dans ma liste de méthodes que j'obtiens cette erreur:

InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()

C'est ma méthode:

    [HttpGet("{currentPage}/{pageSize}/")]
    [HttpGet("{currentPage}/{pageSize}/{search}")]
    public ListResponseVM<ClientVM> GetClients([FromRoute] int currentPage, int pageSize, string search)
    {
        var resp = new ListResponseVM<ClientVM>();
        var items = _context.Clients
            .Include(i => i.Contacts)
            .Include(i => i.Addresses)
            .Include("ClientObjectives.Objective")
            .Include(i => i.Urls)
            .Include(i => i.Users)
            .Where(p => string.IsNullOrEmpty(search) || p.CompanyName.Contains(search))
            .OrderBy(p => p.CompanyName)
            .ToPagedList(pageSize, currentPage);

        resp.NumberOfPages = items.TotalPage;

        foreach (var item in items)
        {
            var client = _mapper.Map<ClientVM>(item);

            client.Addresses = new List<AddressVM>();
            foreach (var addr in item.Addresses)
            {
                var address = _mapper.Map<AddressVM>(addr);
                address.CountryCode = addr.CountryId;
                client.Addresses.Add(address);
            }

            client.Contacts = item.Contacts.Select(p => _mapper.Map<ContactVM>(p)).ToList();
            client.Urls = item.Urls.Select(p => _mapper.Map<ClientUrlVM>(p)).ToList();
            client.Objectives = item.Objectives.Select(p => _mapper.Map<ObjectiveVM>(p)).ToList();
            resp.Items.Add(client);
        }

        return resp;
    }

Je suis un peu perdu, surtout parce qu'elle fonctionne quand je le lance en local, mais quand je déployer pour ma mise en scène server (IIS 8.5) il me met cette erreur et il fonctionnait normalement. L'erreur a commencé à apparaître après que je l'augmentation de la longueur max d'un de mes modèles. J'ai aussi mis à jour la longueur maximum de la Vue correspondante Modèle. Et il existe de nombreuses autres méthodes qui sont très semblables et qu'ils sont au travail.

J'ai eu un Hangfire travail en cours d'exécution, mais ce travail n'a pas la même entité. C'est tout ce que je peux penser pour être pertinent. Toutes les idées de ce qui pourrait être la cause?

223voto

alsami Points 3693

Je ne suis pas sûr si vous utilisez du Cio et de l'Injection de Dépendance pour résoudre votre DbContext où il pourrait être utilisé. Si vous le faites et que vous utilisez natif du Cio de .NET de Base (ou de tout autre Cio-Conteneur) et vous obtenez cette erreur, assurez-vous d'enregistrer votre DbContext Transitoire. Faire

services.AddTransient<MyContext>();

OU

services.AddDbContext<MyContext>(ServiceLifetime.Transient);

au lieu de

services.AddDbContext<MyContext>();

AddDbContext ajoute le contexte comme l'étendue, qui pourraient causer des problèmes lorsque vous travaillez avec plusieurs threads.

Aussi async / await opérations peuvent provoquer ce comportement, lors de l'utilisation asynchrone des expressions lambda.

L'ajout transitoire a aussi ses inconvénients. Vous ne serez pas en mesure d'apporter des modifications à certains entité sur plusieurs classes à l'aide du contexte, parce que chaque classe aura son propre instance de votre DbContext.

199voto

Hamid Nasirloo Points 313

Cette erreur est dans certains cas causée par ce scénario: vous appelez une méthode asynchrone mais vous n’avez pas utilisé attendre avant d’appeler la méthode. mon problème résolu en ajoutant wait avant la méthode. Cependant, la réponse peut ne pas être liée à la question mentionnée mais elle peut aider à une erreur similaire.

55voto

Gabriel Luci Points 6259

L'exception signifie que _context est utilisé par les deux fils en même temps; les deux fils dans la même demande, ou par les deux demandes.

Est votre _context déclaré statique peut-être? Il ne devrait pas être.

Ou êtes-vous en appelant GetClients plusieurs fois dans la même demande à partir de quelque part d'autre dans votre code?

Vous avez peut-être déjà fait, mais idéalement, vous seriez à l'aide de l'injection de dépendance pour votre DbContext, ce qui signifie que vous serez en utilisant AddDbContext() de votre Démarrage.cs, et votre contrôleur constructeur va ressembler à quelque chose comme ceci:

private readonly MyDbContext _context; //not static

public MyController(MyDbContext context) {
    _context = context;
}

Si votre code n'est pas comme cela, nous montrer et peut-être nous pouvons vous aider davantage.

23voto

Raynlaze Points 21

J'ai eu la même erreur. C'est arrivé parce que j'ai appelé une méthode construite comme public async void ... au lieu de public async Task ... .

4voto

J'ai fait face au même problème, mais la raison en était aucune de celles énumérées ci-dessus. J'ai créé une tâche, créé une étendue à l'intérieur de la tâche et demandé au conteneur d'obtenir un service. Cela a bien fonctionné, mais j’ai utilisé un deuxième service à l’intérieur de la tâche et j’ai oublié de le demander également. À cause de cela, le 2e service utilisait un DbContext déjà supprimé.

 Task task = Task.Run(() =>
    {
        using (var scope = serviceScopeFactory.CreateScope())
        {
            var otherOfferService = scope.ServiceProvider.GetService<IOfferService>();
            // everything was ok here. then I did: 
            productService.DoSomething(); // (from the main scope) and this failed because the db context associated to that service was already disposed.
            ...
        }
    }
 

J'aurais dû faire ceci:

 var otherProductService = scope.ServiceProvider.GetService<IProductService>();
otherProductService.DoSomething();
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X