Entity Framework Core: uma segunda operação iniciada neste contexto antes da conclusão de uma operação anterior

88

Estou trabalhando em um projeto ASP.Net Core 2.0 usando 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"/>

E em um dos métodos de minha lista, estou recebendo este erro:

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()

Este é o meu método:

    [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;
    }

Estou um pouco perdido, especialmente porque funciona quando o executo localmente, mas quando implanto no meu servidor de teste (IIS 8.5), recebo esse erro e estava funcionando normalmente. O erro começou a aparecer depois de aumentar o comprimento máximo de um dos meus modelos. Eu também atualizei o comprimento máximo do modelo de vista correspondente. E existem muitos outros métodos de lista que são muito semelhantes e estão funcionando.

Eu tinha um trabalho Hangfire em execução, mas esse trabalho não usa a mesma entidade. Isso é tudo que consigo pensar para ser relevante. Alguma ideia do que pode estar causando isso?

André luiz
fonte
1
Verifique isso .
Berkay
2
@Berkay Eu vi essa e muitas outras perguntas semelhantes e as experimentei. Meu método era assíncrono e fiz a sincronização para evitar esses problemas. Também tento remover o mapeamento, também tentei remover o .ToPagedList ele continua jogando o erro.
André Luiz
Seria bom ver um rastreamento de pilha completo
Evk
E para saber se vários resultados ativos estão ativados
Jay
Tendo tido o mesmo problema, descobri que tinha números inteiros anuláveis ​​em minha tabela de banco de dados. assim que defini minhas propriedades de modelo de entidade para coincidir com int's anuláveis, tudo começou a funcionar, então, as mensagens foram enganosas para mim ...!
AlwaysLearning

Respostas:

87

Não tenho certeza se você está usando IoC e injeção de dependência para resolver seu DbContext onde quer que ele possa ser usado. Se você fizer isso e estiver usando IoC nativo do .NET Core (ou qualquer outro IoC-Container) e estiver recebendo este erro, certifique-se de registrar seu DbContext como Transiente. Faz

services.AddTransient<MyContext>();

OU

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

ao invés de

services.AddDbContext<MyContext>();

AddDbContext adiciona o contexto como escopo, o que pode causar problemas ao trabalhar com vários threads.

Além disso, operações assíncronas / aguardar podem causar esse comportamento, ao usar expressões lambda assíncronas.

Adicioná-lo como temporário também tem suas desvantagens. Você não poderá fazer alterações em alguma entidade em várias classes que estão usando o contexto porque cada classe obterá sua própria instância de seu DbContext.

A explicação simples para isso é que a DbContextimplementação não é segura para threads. Você pode ler mais sobre isso aqui

alsami
fonte
1
Quando eu uso o transiente, recebo os seguintes erros de conexão (fechada ou descartada) 'OmniService.DataAccess.Models.OmniServiceDbContext'. System.ObjectDisposedException: Não é possível acessar um objeto descartado. Uma causa comum desse erro é descartar um contexto que foi resolvido da injeção de dependência e, posteriormente, tentar usar a mesma instância de contexto em outro lugar em seu aplicativo. Isso pode ocorrer se você estiver chamando Dispose () no contexto ou agrupando o contexto em uma instrução using. ... Nome do objeto: 'AsyncDisposer'.
David
3
Olá David! Eu acho que você está usando Task.Run(async () => context.Set...)sem esperar ou criando um contexto db com escopo sem esperar o resultado. Isso significa que seu contexto provavelmente já está descartado ao acessá-lo. Se você estiver no Microsoft DI, deve criar um escopo de dependência dentro dele Task.Run. Verifique esses links também. stackoverflow.com/questions/45047877/… docs.microsoft.com/en-us/dotnet/api/…
alsami
3
Como apontado anteriormente, se você deixar de chamar um método assíncrono com a palavra-chave await, você enfrentará esse problema.
Yennefer
Isso me ajudou. Estou injetando dependências em um novo thread de um serviço hospedado quando recebemos uma nova mensagem de uma fila. Tornar meu contexto transitório corrigiu a exceção
Cale
3
@alsami você é meu herói. 6 horas de depuração dolorosa. Essa foi a solução. Se outra pessoa estiver injetando IHttpContextAccessor no DbContext e as Declarações forem nulas, esta é a solução. Muito obrigado cara.
jcmontx
55

Em alguns casos, esse erro ocorre ao chamar um método assíncrono sem a awaitpalavra - chave, o que pode ser resolvido simplesmente adicionando awaitantes da chamada do método. no entanto, a resposta pode não estar relacionada à pergunta mencionada, mas pode ajudar a resolver um erro semelhante.

Hamid Nasirloo
fonte
4
Isso aconteceu comigo. Mudando First()para await / FirstAsync()funcionou.
Guilherme
Voto positivo. Consulte também jimlynn.wordpress.com/2017/11/16/… Jim Lynn "ERRO DE ENTITY FRAMEWORK: UMA SEGUNDA OPERAÇÃO INICIADA NESTE CONTEXTO ANTES DE UMA OPERAÇÃO ANTERIOR CONCLUÍDA. NENHUMA INSTÂNCIA MEMBROS NÃO SÃO GARANTIDOS PARA ESTAR SEGURO DE LINHA."
granadaCoder
Obrigado por isso! Esse era exatamente o meu problema ... Esqueci de adicionar um await em um mdethod assíncrono.
AxleWack
Aconteceu comigo também, e esse comentário ajudou, pois procurei onde esqueci uma espera perdida. Assim que o encontrei, o problema foi resolvido.
Zion Hai
42

A exceção significa que _contextestá sendo usado por dois threads ao mesmo tempo; dois threads na mesma solicitação ou por duas solicitações.

A sua _contextdeclaração estática, talvez? Não deveria ser.

Ou você está chamando GetClientsvárias vezes na mesma solicitação de algum outro lugar no seu código?

Você pode já estar fazendo isso, mas idealmente, você usaria injeção de dependência para o seu DbContext, o que significa que você estará usando AddDbContext()em seu Startup.cs, e seu construtor de controlador será parecido com isto:

private readonly MyDbContext _context; //not static

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

Se o seu código não é assim, mostre-nos e talvez possamos ajudar mais.

Gabriel luci
fonte
1
Provavelmente é o emprego que tenho. Consegui resolver, veja minha resposta. Mas estou marcando a sua como a certa
André Luiz
Meu código é exatamente assim e muitas vezes rastreamos "Uma segunda operação iniciada neste contexto antes de uma operação assíncrona anterior ser concluída. Use 'await' para garantir que qualquer operação assíncrona seja concluída antes de chamar outro método neste contexto. Quaisquer membros de instância não são garantido para ser thread-safe. - em System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered () ".
NMathur
@NMathur Você está usando seu _contextobjeto em outras threads? Como dentro de um Task.Run()por exemplo?
Gabriel Luci
@GabrielLuci todos os meus métodos são assíncronos como abaixo, isso causará o problema. Meu conhecimento sobre este assunto é muito pequeno. Você pode sugerir onde e o que devo ler em detalhes para entender esses comportamentos? public async Tarefa <List <Item>> GetItems (int orderId) {List <Item> items = await _context.Item.Where (x => x.OrderId == orderId) .ToListAsync (); devolver itens; }
NMathur
@NMathur Isso parece bom. Apenas certifique-se de estar sempre usando awaitmétodos assíncronos. Se você não usar await, você pode acidentalmente entrar em multi-threading.
Gabriel Luci,
8
  • Resolva meu problema usando esta linha de código em meu arquivo Startup.cs.
    Adicionar um serviço temporário significa que cada vez que o serviço é solicitado, uma nova instância é criada quando você está trabalhando com injeção de dependência

           services.AddDbContext<Context>(options =>
                            options.UseSqlServer(_configuration.GetConnectionString("ContextConn")),
                 ServiceLifetime.Transient);
    
Muhammad Armaghan
fonte
6

Eu tive o mesmo problema e descobri que o serviço aos pais era um singelton. Portanto, o contexto tornou-se automaticamente único também. Embora tenha sido declarado como Per Life Time Scoped in DI.

Injetando serviço com diferentes vidas em outro

  1. Nunca injete serviços com escopo e temporário no serviço Singleton. (Isso converte efetivamente o serviço transitório ou com escopo no singleton.)

  2. Nunca injete serviços temporários em serviço com escopo (isso converte o serviço transiente em serviço com escopo definido).

DiPix
fonte
este era exatamente o meu problema
Jonesopolis
Esse era o meu problema também. Eu estava registrando uma classe de manipulador como singleton e o DbContext como temporário. Tive que usar ServiceProvider dentro da classe Handler para obter uma instância transitória do contêiner de DI toda vez que o Handler é atingido
Daiana Sodré
5

Eu tive o mesmo erro. Aconteceu porque chamei um método que foi construído como em public async void ...vez de public async Task ....

Raynlaze
fonte
4

Acho que essa resposta ainda pode ajudar alguém e economizar muitas vezes. Resolvi um problema semelhante mudando IQueryablepara List(ou para array, coleção ...).

Por exemplo:

var list=_context.table1.where(...);

para

var list=_context.table1.where(...).ToList(); //or ToArray()...
Makhidi Masimov
fonte
2
IMHO, Esta resposta não merece pontos negativos, É apenas mal expressa. .ToList () realmente resolve a maioria dos problemas "uma segunda operação ..." devido ao fato de que força a avaliação imediata da expressão. Dessa forma, não há operações de contexto de enfileiramento.
vassilag
Esse foi o problema no meu caso. Eu tinha xxx.Contains (z.prop) em uma cláusula where de uma consulta. xxx deveria ser um array int [] distinto resolvido de uma consulta anterior. Infelizmente, no momento em que ocorreu a segunda consulta, xxx ainda era um IQueryable. Adicionar xxx.ToArray () antes da segunda consulta corrigiu meu problema.
Jason Butera
2

Enfrentei o mesmo problema, mas o motivo não foi nenhum dos listados acima. Eu criei uma tarefa, criei um escopo dentro da tarefa e pedi ao container para obter um serviço. Funcionou bem, mas depois usei um segundo serviço dentro da tarefa e esqueci de solicitá-lo também para o novo escopo. Por conta disso, o 2º serviço estava utilizando um DbContext que já estava descartado.

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.
            ...
        }
    }

Eu deveria ter feito isso:

var otherProductService = scope.ServiceProvider.GetService<IProductService>();
otherProductService.DoSomething();
Francisco Goldenstein
fonte
O contexto não seria exposto apenas depois que tudo no bloco em uso tivesse concluído a execução?
Sello Mkantjwa
Quando a ação é descartada, tudo está disposto naquele escopo. Se você tiver uma tarefa em execução em segundo plano e essa tarefa for mais longa que a ação, você terá esse problema, a menos que crie um novo escopo para a tarefa, assim como eu fiz no exemplo. Por outro lado, se sua tarefa demorar muito ou você quiser ter 100% de certeza de que será executada, talvez seja necessário usar uma fila. Se você estiver usando o Azure, poderá usar as filas do Service Bus.
Francisco Goldenstein
2

Entity Framework Core não oferece suporte a várias operações paralelas sendo executadas no mesmo DbContext instância. Isso inclui a execução paralela de asyncconsultas e qualquer uso simultâneo explícito de vários threads. Portanto, sempre await asyncchame imediatamente ou use DbContextinstâncias separadas para operações executadas em paralelo.

Ehsan Gondal
fonte
1

Minha situação é diferente: eu estava tentando propagar o banco de dados com 30 usuários, pertencentes a funções específicas, então estava executando este código:

for (var i = 1; i <= 30; i++)
{
    CreateUserWithRole("Analyst", $"analyst{i}", UserManager);
}

Esta era uma função de sincronização. Dentro dele, eu tinha 3 ligações para:

UserManager.FindByNameAsync(username).Result
UserManager.CreateAsync(user, pass).Result
UserManager.AddToRoleAsync(user, roleName).Result

Quando substituí .Resultpor .GetAwaiter().GetResult(), esse erro foi embora.

Catalin
fonte
0

Eu recebi a mesma mensagem. Mas não faz sentido no meu caso. Meu problema é que usei uma propriedade "NotMapped" por engano. Provavelmente significa apenas um erro de sintaxe Linq ou classe de modelo em alguns casos. A mensagem de erro parece enganosa. O significado original desta mensagem é que você não pode chamar async no mesmo dbcontext mais de uma vez na mesma solicitação.

[NotMapped]
public int PostId { get; set; }
public virtual Post Post { get; set; }

Você pode verificar este link para obter detalhes, https://www.softwareblogs.com/Posts/Details/5/error-a-second-operation-started-on-this-context-before-a-previous-operation-completed

Sharon Zhou
fonte
0

Tenho um serviço em segundo plano que executa uma ação para cada entrada em uma tabela. O problema é que, se eu iterar e modificar alguns dados, todos na mesma instância do DbContext, esse erro ocorre.

Uma solução, conforme mencionado neste tópico, é alterar o tempo de vida do DbContext para temporário, definindo-o como

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

mas porque eu faço alterações em vários serviços diferentes e as comprometo de uma vez usando o SaveChanges() método, essa solução não funciona no meu caso.

Como meu código é executado em um serviço, eu estava fazendo algo como

using (var scope = Services.CreateScope())
{
   var entities = scope.ServiceProvider.GetRequiredService<IReadService>().GetEntities();
   var writeService = scope.ServiceProvider.GetRequiredService<IWriteService>();
   foreach (Entity entity in entities)
   {
       writeService.DoSomething(entity);
   } 
}

poder usar o serviço como se fosse um simples pedido. Então, para resolver o problema, apenas divido o escopo único em dois, um para a consulta e outro para as operações de gravação, assim:

using (var readScope = Services.CreateScope())
using (var writeScope = Services.CreateScope())
{
   var entities = readScope.ServiceProvider.GetRequiredService<IReadService>().GetEntities();
   var writeService = writeScope.ServiceProvider.GetRequiredService<IWriteService>();
   foreach (Entity entity in entities)
   {
       writeService.DoSomething(entity);
   } 
}

Assim, existem efetivamente duas instâncias diferentes do DbContext sendo usado.

Outra solução possível seria certificar-se de que a operação de leitura foi encerrada antes de iniciar a iteração. Isso não é muito prático no meu caso, porque poderia haver muitos resultados que precisariam ser carregados na memória para a operação que tentei evitar usando um Queryable em primeiro lugar.

NiPfi
fonte
0

Consegui obter esse erro passando um IQueryablepara um método que usava essa 'lista' IQueryable como parte de uma outra consulta para o mesmo contexto.

public void FirstMethod()
{
    // This is returning an IQueryable
    var stockItems = _dbContext.StockItems
        .Where(st => st.IsSomething);

    SecondMethod(stockItems);
}

public void SecondMethod(IEnumerable<Stock> stockItems)
{
    var grnTrans = _dbContext.InvoiceLines
        .Where(il => stockItems.Contains(il.StockItem))
        .ToList();
}

Para impedir que isso aconteça, usei a abordagem aqui e materializei essa lista antes de passar o segundo método, alterando a chamada SecondMethodpara serSecondMethod(stockItems.ToList()

tomRedox
fonte
Isso resolveu o problema, mas não vai diminuir o desempenho? Existe alguma solução alternativa?
Dheeraj Kumar
0

Primeiro, vote positivamente (pelo menos) na resposta de alsami. Isso me colocou no caminho certo.

Mas para aqueles que estão fazendo IoC, aqui está um mergulho um pouco mais profundo.

Meu erro (igual aos outros)

Ocorreram um ou mais erros. (Uma segunda operação foi iniciada neste contexto antes da conclusão de uma operação anterior. Isso geralmente é causado por threads diferentes usando a mesma instância de DbContext. Para obter mais informações sobre como evitar problemas de threading com DbContext, consulte https://go.microsoft.com / fwlink /? linkid = 2097913. )

Minha configuração de código. "Apenas o básico" ...

public class MyCoolDbContext: DbContext{
    public DbSet <MySpecialObject> MySpecialObjects {        get;        set;    }
}

e

public interface IMySpecialObjectDomainData{}

e (observe que MyCoolDbContext está sendo injetado)

public class MySpecialObjectEntityFrameworkDomainDataLayer: IMySpecialObjectDomainData{
    public MySpecialObjectEntityFrameworkDomainDataLayer(MyCoolDbContext context) {
        /* HERE IS WHERE TO SET THE BREAK POINT, HOW MANY TIMES IS THIS RUNNING??? */
        this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);
    }
}

e

public interface IMySpecialObjectManager{}

e

public class MySpecialObjectManager: IMySpecialObjectManager
{
    public const string ErrorMessageIMySpecialObjectDomainDataIsNull = "IMySpecialObjectDomainData is null";
    private readonly IMySpecialObjectDomainData mySpecialObjectDomainData;

    public MySpecialObjectManager(IMySpecialObjectDomainData mySpecialObjectDomainData) {
        this.mySpecialObjectDomainData = mySpecialObjectDomainData ?? throw new ArgumentNullException(ErrorMessageIMySpecialObjectDomainDataIsNull, (Exception)null);
    }
}

E, finalmente, minha classe multithread, sendo chamada de um aplicativo de console (aplicativo de interface de linha de comando)

    public interface IMySpecialObjectThatSpawnsThreads{}

e

public class MySpecialObjectThatSpawnsThreads: IMySpecialObjectThatSpawnsThreads
{
    public const string ErrorMessageIMySpecialObjectManagerIsNull = "IMySpecialObjectManager is null";

    private readonly IMySpecialObjectManager mySpecialObjectManager;

    public MySpecialObjectThatSpawnsThreads(IMySpecialObjectManager mySpecialObjectManager) {
        this.mySpecialObjectManager = mySpecialObjectManager ?? throw new ArgumentNullException(ErrorMessageIMySpecialObjectManagerIsNull, (Exception)null);
    }
}

e o acúmulo de DI. (Novamente, isso é para um aplicativo de console (interface de linha de comando) ... que exibe um comportamento ligeiramente diferente dos aplicativos da web)

private static IServiceProvider BuildDi(IConfiguration configuration) {
    /* this is being called early inside my command line application ("console application") */

    string defaultConnectionStringValue = string.Empty; /* get this value from configuration */

    ////setup our DI
    IServiceCollection servColl = new ServiceCollection()
        ////.AddLogging(loggingBuilder => loggingBuilder.AddConsole())

        /* THE BELOW TWO ARE THE ONES THAT TRIPPED ME UP.  */
        .AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
    .AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()

    /* so the "ServiceLifetime.Transient" below................is what you will find most commonly on the internet search results */
     # if (MY_ORACLE)
        .AddDbContext<ProvisioningDbContext>(options => options.UseOracle(defaultConnectionStringValue), ServiceLifetime.Transient);
     # endif

     # if (MY_SQL_SERVER)
        .AddDbContext<ProvisioningDbContext>(options => options.UseSqlServer(defaultConnectionStringValue), ServiceLifetime.Transient);
     # endif

    servColl.AddSingleton <IMySpecialObjectThatSpawnsThreads,        MySpecialObjectThatSpawnsThreads>();

    ServiceProvider servProv = servColl.BuildServiceProvider();

    return servProv;
}

Os que me surpreenderam foram os (mudar para) transitórios para

        .AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
    .AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()

Observe, eu acho que como IMySpecialObjectManager estava sendo injetado em "MySpecialObjectThatSpawnsThreads", esses objetos injetados precisavam ser Transientes para completar a cadeia.

O ponto é ....... não era apenas o (My) DbContext que precisava .Transient ... mas uma parte maior do gráfico DI.

Dica de depuração:

Está linha:

this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);

Coloque seu ponto de interrupção do depurador lá. Se seu MySpecialObjectThatSpawnsThreads está gerando um número N de threads (digamos 10 threads, por exemplo) ...... e essa linha está sendo atingida apenas uma vez ... esse é o seu problema. Seu DbContext está cruzando tópicos.

BÔNUS:

Eu sugeriria a leitura deste url / artigo abaixo (antigo, mas bom) sobre as diferenças entre aplicativos da web e aplicativos de console

https://mehdi.me/ambient-dbcontext-in-ef6/

Aqui está o cabeçalho do artigo, caso o link mude.

GERENCIANDO DBCONTEXT DA MANEIRA CERTA COM ENTIDADE FRAMEWORK 6: UM GUIA EM PROFUNDIDADE Mehdi El Gueddari

Eu encontrei este problema com WorkFlowCore https://github.com/danielgerlag/workflow-core

  <ItemGroup>
    <PackageReference Include="WorkflowCore" Version="3.1.5" />
  </ItemGroup>

exemplo de código abaixo .. para ajudar futuros pesquisadores da Internet

 namespace MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Workflows
    {
        using System;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Constants;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Glue;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.WorkflowSteps;

        using WorkflowCore.Interface;
        using WorkflowCore.Models;

        public class MySpecialObjectInterviewDefaultWorkflow : IWorkflow<MySpecialObjectInterviewPassThroughData>
        {
            public const string WorkFlowId = "MySpecialObjectInterviewWorkflowId";

            public const int WorkFlowVersion = 1;

            public string Id => WorkFlowId;

            public int Version => WorkFlowVersion;

            public void Build(IWorkflowBuilder<MySpecialObjectInterviewPassThroughData> builder)
            {
                builder
                             .StartWith(context =>
                    {
                        Console.WriteLine("Starting workflow...");
                        return ExecutionResult.Next();
                    })

                        /* bunch of other Steps here that were using IMySpecialObjectManager.. here is where my DbContext was getting cross-threaded */


                    .Then(lastContext =>
                    {
                        Console.WriteLine();

                        bool wroteConcreteMsg = false;
                        if (null != lastContext && null != lastContext.Workflow && null != lastContext.Workflow.Data)
                        {
                            MySpecialObjectInterviewPassThroughData castItem = lastContext.Workflow.Data as MySpecialObjectInterviewPassThroughData;
                            if (null != castItem)
                            {
                                Console.WriteLine("MySpecialObjectInterviewDefaultWorkflow complete :)  {0}   -> {1}", castItem.PropertyOne, castItem.PropertyTwo);
                                wroteConcreteMsg = true;
                            }
                        }

                        if (!wroteConcreteMsg)
                        {
                            Console.WriteLine("MySpecialObjectInterviewDefaultWorkflow complete (.Data did not cast)");
                        }

                        return ExecutionResult.Next();
                    }))

                    .OnError(WorkflowCore.Models.WorkflowErrorHandling.Retry, TimeSpan.FromSeconds(60));

            }
        }
    }

e

ICollection<string> workFlowGeneratedIds = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    MySpecialObjectInterviewPassThroughData currentMySpecialObjectInterviewPassThroughData = new MySpecialObjectInterviewPassThroughData();
                    currentMySpecialObjectInterviewPassThroughData.MySpecialObjectInterviewPassThroughDataSurrogateKey = i;

                    ////  private readonly IWorkflowHost workflowHost;
                    string wfid = await this.workflowHost.StartWorkflow(MySpecialObjectInterviewDefaultWorkflow.WorkFlowId, MySpecialObjectInterviewDefaultWorkflow.WorkFlowVersion, currentMySpecialObjectInterviewPassThroughData);
                    workFlowGeneratedIds.Add(wfid);
                }
granadaCoder
fonte
0

No meu caso, eu uso um componente de modelo no Blazor.

 <BTable ID="Table1" TotalRows="MyList.Count()">

O problema é chamar um método (Count) no cabeçalho do componente. Para resolver o problema, mudei assim:

int total = MyList.Count();

e depois :

<BTable ID="Table1" TotalRows="total">
Ali Borjian
fonte
0

Sei que esse problema foi perguntado há dois anos, mas eu simplesmente tive esse problema e a correção que usei realmente ajudou.

Se você estiver fazendo duas consultas com o mesmo Contexto - pode ser necessário remover o AsNoTracking. Se você usar, AsNoTrackingestará criando um novo leitor de dados para cada leitura. Dois leitores de dados não podem ler os mesmos dados.

Cornelis de Jager
fonte
0

No meu caso eu estava usando um bloqueio que não permite o uso de await e não cria um aviso do compilador quando você não espera um async.

O problema:

lock (someLockObject) {
    // do stuff
    context.SaveChangesAsync();
}

// some other code somewhere else doing await context.SaveChangesAsync() shortly after the lock gets the concurrency error

A correção: aguarde o assíncrono dentro do bloqueio, tornando-o bloqueado com um .Wait ()

lock (someLockObject) {
    // do stuff
    context.SaveChangesAsync().Wait();
}
Tikall
fonte
0

Outro caso possível: se você usa a conexão direta, não esqueça de fechar se. Eu precisava executar uma consulta SQL arbitrária e ler o resultado. Esta foi uma solução rápida, eu não queria definir uma classe de dados, não configurar uma conexão SQL "normal". Então, simplesmente reutilizei a conexão de banco de dados do EFC como var connection = Context.Database.GetDbConnection() as SqlConnection. Certifique-se de ligar connection.Close()antes de fazer Context.SaveChanges().

klenium
fonte
-1

Tive o mesmo problema quando tento usar FirstOrDefaultAsync() o método assíncrono no código abaixo. E quando eu consertei FirstOrDefault()- o problema foi resolvido!

_context.Issues.Add(issue);
        await _context.SaveChangesAsync();

        int userId = _context.Users
            .Where(u => u.UserName == Options.UserName)
            .FirstOrDefaultAsync()
            .Id;
...
JuSik404
fonte
1
Não está relacionado a FirstOrDefault () ou FirstOrDefaultAsync (). É sobre o uso de dbContext.
sajadre
-2

Se o seu método está retornando algo de volta, você pode resolver esse erro colocando .Resultno final do trabalho e .Wait()se não retornar nada.

Hasan_H
fonte
-6

Eu apenas consegui fazer funcionar novamente. Não faz muito sentido, mas funcionou:

  1. Remova Hangfire da inicialização (eu estava criando meu trabalho lá)
  2. Excluído o banco de dados hangfire
  3. Reiniciou o servidor

Vou investigar mais tarde, mas o método que chamei com hangfire recebe um DBContext e essa é a causa possível.

André luiz
fonte