none
Mensagem estranho de travamento... RRS feed

  • Pergunta

  • Pessoal, tenho uma aplica;áo q precisa inserir no banco uns 1500 registros.

    to tentando fazer esse processamento de inserir linha a linha num método com await:

    await gravarNoBanco(registros);

    ele começa a gravar, quando tá lá pela centésima linha aparece o seguinte erro:

    O CLR não conseguiu fazer a transição do contexto COM 0x857f50 para o contexto COM 0x8580c0 em 60 segundos. O thread que possui o context/apartment de destino está provavelmente fazendo uma espera sem bombeamento ou processando uma operação de execução muito longa sem bombeamento das mensagens do Windows. Geralmente, essa situação tem um impacto negativo no desempenho e pode até mesmo levar à falta de resposta do aplicativo ou ao acúmulo contínuo de uso de memória com o tempo. Para evitar esse problema, todos os threads com um único apartment em thread (STA) devem usar primitivos de espera de bombeamento (como CoWaitForMultipleHandles) e bombear rotineiramente as mensagens durante operações de execução longa.

    to usando sqlite com EF.

    Alguém sabe me explicar o q tá havendo?

    Outra coisa, embore eu use await, o processamento congela a janela do aplicativo enquanto ele está gravando os registros no banco.... como fazer pra evitar isso?


    Se a resposta foi útil, por favor marque como útil. Leia a bíblia.

    segunda-feira, 8 de abril de 2013 14:25

Respostas

  • Então Tiano,

    é o seguinte, parece que para cada Anuncio tem 1 QS, certo?

    Então, se no Modelo do banco o relacionamento foi feito de forma correta, a ferramenta que importa o modelo do EF deve ter criado uma propriedade do tipo QS para o seu anuncio.

    using(myEntit db = new myEntit()){ Anuncio novoAnuncio = new Anuncio(); novoAnuncio.Id_Template = idTemplate; novoAnuncio.Texto = itemLinhasValidas; novoAnuncio.Data_Criacao = DateTime.Now.ToString(formatoData); novoAnuncio.Data_Ultima_Atualizacao = DateTime.Now.ToString(formatoData);

    int qsLV = -1; if (itemLinhasValidas.Split('\t')[indexColunaQS] == "") qsLV = 0; else qsLV = Convert.ToInt32(itemLinhasValidas.Split('\t')[indexColunaQS]);

    QS novoQS = new QS(); //novoQS.Id_Anuncio = novoAnuncio.Id_Anuncio; // Não necessário pois o EF atribui automaticamente novoQS.Valor_QS = qsLV; novoQS.Variacao = 0; novoAnuncio.QS = novoQS; db.Anuncio.Add(novoAnuncio); db.SaveChanges(); }

    Tenta fazer o que eu coloquei acima!!!

    Abraço!!

    • Marcado como Resposta Tianodraco segunda-feira, 8 de abril de 2013 18:43
    segunda-feira, 8 de abril de 2013 17:55

Todas as Respostas

  • Olá Tiano,

    Há um tempo atras tive esse problema e a solução encontra-se neste link:

    http://blogs.microsoft.co.il/blogs/adlaim/archive/2007/08/06/The-CLR-has-been-unable-to-transition-from-COM-context.aspx

    Abraço!

    segunda-feira, 8 de abril de 2013 14:31
  • Sobre o seu 2o Problema,

    use o comando:

    Application.DoEvents();

    para que sua aplicação execute o Repaint no form.

    Abraço!!!

    segunda-feira, 8 de abril de 2013 14:35
  • Fábio obrigado por sua resposta.

    Veja o seguinte trecho de código

    using(myEntities db = new myEntities()){
    
    for(i = 0; i <= 1300; i++){
    
    Anuncio novoAnuncio = new Anuncio();
    
    novoAnuncio.Texto = "Este é o anúncio de número: " + i;
    
    db.Anuncio.Add(novoAnuncio);
    
    db.SaveChanges();
    
    }
    }

    Desculpe se tiver algum erro no código o fiz agora só pra ilustrar....

    É desse jeito acima q eu to fazendo a inserção dos meus registros... mas pra inserir cerca de 1300 registro tá demorando quase 7 minutos!

    Tem como eu empiulhar esses registros no EF e depois enviar em lote, salvando tudo de uma vez com um único SaveChanges?


    Se a resposta foi útil, por favor marque como útil. Leia a bíblia.

    segunda-feira, 8 de abril de 2013 17:17
  • Sim...

    Retire o SaveChanges() do for!!!

    using(myEntities db = new myEntities())
    {
    for(i = 0; i <= 1300; i++){
    Anuncio novoAnuncio = new Anuncio();
    novoAnuncio.Texto = "Este é o anúncio de número: " + i;
    db.Anuncio.Add(novoAnuncio);
    }
    db.SaveChanges();
    }
    Abraço!!!

    segunda-feira, 8 de abril de 2013 17:21
  • Fábio, desculpa minha ignorância, eu sem querer esqueci uma parte importante... vou por aqui o código completo pra vc ver:

    using(myEntit db = new myEntit()){
    Anuncio novoAnuncio = new Anuncio();
                            novoAnuncio.Id_Template = idTemplate;
                            novoAnuncio.Texto = itemLinhasValidas;
                            novoAnuncio.Data_Criacao = DateTime.Now.ToString(formatoData);
                            novoAnuncio.Data_Ultima_Atualizacao = DateTime.Now.ToString(formatoData);
    
                            db.Anuncio.Add(novoAnuncio);
    
                            db.SaveChanges();
    
                            //GRAVA UM NOVO QS NO BANCO
                            int qsLV = -1;
    
                            if (itemLinhasValidas.Split('\t')[indexColunaQS] == "")
                                qsLV = 0;
                            else
                                qsLV = Convert.ToInt32(itemLinhasValidas.Split('\t')[indexColunaQS]);
    
                            QS novoQS = new QS();
                            novoQS.Id_Anuncio = novoAnuncio.Id_Anuncio;
                            novoQS.Valor_QS = qsLV;
                            novoQS.Variacao = 0;
    
                            db.QS.Add(novoQS);
    
                            db.SaveChanges();
    }

    Se eu tirar o savechanges do loop, a parte em novoQS.Id_Anuncio = novoAnuncio.Id_Anuncio; não fica prejudicada.... pq assim, como o EF sabe qual é o id_Anuncio no banco se o registro não foi gravado no banco (q tem um campo autoincrement nesse campo)?

    Eu tentei aqui de todo jeito e dá erro:

    Não é possível determinar a extremidade principal da relação 'smcdbModel.FK_QS_0_0'. Várias entidades adicionadas podem ter a mesma chave primária.

    A tabela QS possui uma foreign key para a chave primária da tabela Anuncio

    Quando gravo um anuncio, preciso tb depois gravar valores na tabela QS... 




    Se a resposta foi útil, por favor marque como útil. Leia a bíblia.


    • Editado Tianodraco segunda-feira, 8 de abril de 2013 17:46
    segunda-feira, 8 de abril de 2013 17:40
  • Então Tiano,

    é o seguinte, parece que para cada Anuncio tem 1 QS, certo?

    Então, se no Modelo do banco o relacionamento foi feito de forma correta, a ferramenta que importa o modelo do EF deve ter criado uma propriedade do tipo QS para o seu anuncio.

    using(myEntit db = new myEntit()){ Anuncio novoAnuncio = new Anuncio(); novoAnuncio.Id_Template = idTemplate; novoAnuncio.Texto = itemLinhasValidas; novoAnuncio.Data_Criacao = DateTime.Now.ToString(formatoData); novoAnuncio.Data_Ultima_Atualizacao = DateTime.Now.ToString(formatoData);

    int qsLV = -1; if (itemLinhasValidas.Split('\t')[indexColunaQS] == "") qsLV = 0; else qsLV = Convert.ToInt32(itemLinhasValidas.Split('\t')[indexColunaQS]);

    QS novoQS = new QS(); //novoQS.Id_Anuncio = novoAnuncio.Id_Anuncio; // Não necessário pois o EF atribui automaticamente novoQS.Valor_QS = qsLV; novoQS.Variacao = 0; novoAnuncio.QS = novoQS; db.Anuncio.Add(novoAnuncio); db.SaveChanges(); }

    Tenta fazer o que eu coloquei acima!!!

    Abraço!!

    • Marcado como Resposta Tianodraco segunda-feira, 8 de abril de 2013 18:43
    segunda-feira, 8 de abril de 2013 17:55
  • Conceitualmente falando,

    Quanto estamos utilizado o EF, primeiro preenchemos todo o nosso objeto sem se preocupar com os IDs que serão gerados... e depois adicionamos o Objeto ao EntitySet relacionado a este objeto... e depois efetuamos o SaveChanges();

    Por exemplo... Imagine que tenho uma tabela Pedido e outra ItemPedido com relacionamento 1..n.

    Passo 1:
    Criar uma entidade Pedido (chamada de entPedido por exemplo) e preencher com dados do Pedido...

    Passo 2:
    Para cada Item do Pedido, criar uma entidade ItemPedido, preenchê-la, e adicionar a coleção entPedido.ItemPedidos...

    Repare que ainda não obtivemos nenhum ID do banco...

    Quando você executar o db.SaveChanges() os IDs serão criados e preenchidos de acordo com o relacionamento existente no banco.

    Ou seja, não precisa de um SaveChanges() para o Pedido e outro SaveChanges para o ItemPedido...

    Entendeu?

    Abraço!!!

    segunda-feira, 8 de abril de 2013 18:07
  • Fábio, 100% funcional!

    Eis o código funcionando corretamente:

    Anuncio novoAnuncio = new Anuncio();
                            novoAnuncio.Id_Template = idTemplate;
                            novoAnuncio.Texto = itemLinhasValidas;
                            novoAnuncio.Data_Criacao = DateTime.Now.ToString(formatoData);
                            novoAnuncio.Data_Ultima_Atualizacao = DateTime.Now.ToString(formatoData);
                            
                            db.Anuncio.Add(novoAnuncio);
    
                            //GRAVA UM NOVO QS NO BANCO
                            int qsLV = -1;
    
                            if (itemLinhasValidas.Split('\t')[indexColunaQS] == "")
                                qsLV = 0;
                            else
                                qsLV = Convert.ToInt32(itemLinhasValidas.Split('\t')[indexColunaQS]);
    
                            QS novoQS = new QS();
                            novoQS.Anuncio = novoAnuncio;
                            novoQS.Valor_QS = qsLV;
                            novoQS.Variacao = 0;
                            
                            db.QS.Add(novoQS);  

    Muito obrigado. Agora só falta esse processamento não travar a tela do aplicativo... to querendo colocar uma progressbar na tela, pq q a cada iteracao do loop ele va incrementando....

    Vou marcar seus posts como resposta, tem como continuarmos nesse post depois q eu fizer isso?


    Se a resposta foi útil, por favor marque como útil. Leia a bíblia.

    segunda-feira, 8 de abril de 2013 18:33
  • Que bom...

    Sem problemas... Assim que tiver dúvidas ou problemas... pode postar aqui, ou abrir novos posts para outro tipo de problemas...

    de qualquer forma... sempre estou ligado aqui no forum!!!

    E... não esqueça de marcar meus replies como resposta blz?

    Abraço!!!


    segunda-feira, 8 de abril de 2013 18:39