none
db.SaveChanges() tardio de um EF dentro de um loop

    Pergunta

  • Pessoal, tem um programa q varre uma lista de URL's, procura um vaor e salva a informação nos registros do banco de dados.

    Coloquei o WebClient num método assíncrono e está funcionando bem, só q percebi uma lentidão pq coloquei nesse método.

    Tentei passar o entities como parâmetro, configurar minhas propriedades dentro do loop e depois, já fora do loop das url's, dar um savechanges().... mas aparece uma mensagem dizend q o entities foi disposto (encerrado).

    Abaixo posto o código:

    Aqui fico enviand as URL's para o procedimento...

    for (int a = 0; a < colunasLinks.Count; a++)
                {
                    for (int i = 0; i < dtGeral.Rows.Count; i++)
                    {
                        await goCrawler(url, xPathPreco, xPathKeyword, keyword, dtGeral, i, nomeColunaEspecial_3, nomeColunaEspecial_4, nomeColunaEspecial_6, nomeColunaEspecial_7, encoding);
    
                    }
                }

    Dentro do procedimento "goCrwler" utilizo o WebClient pra fazer o download do html, procuro uma informação nesse html e gravo no banco:

    using (smcdbEntities db = new smcdbEntities())
                    {
                        Anuncio anuncio = (from a in db.Anuncio
                                           where a.Texto.Contains(nomeCmpaign) &&
                                           a.Texto.Contains(url)
                                           select a).FirstOrDefault();
    
                        anuncio.EmEstoque = (emEstoque == "True" ? "S" : "N");
                    }

    A variável emEstoque já possui o valor (verdadeiro ou falso), dependendo se uma string foi ou não encontrada no HTML que foi baixado. Então o próximo passo é gravar no bacno.

    Assim, funciona, mas fico dando  savechanges o tempo todo a cada URL.... qeria otimizar pra dar só uma vez, encntrando um meio de passar o entities como parametro da funcao sem q ele sofra o disposed.


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

    quarta-feira, 17 de abril de 2013 12:47

Todas as Respostas

  • Acho que o que vc quer fazer é marcar todos os registros para alteração e executar o processo de gravação somente uma vez no final correto ?

    Você pode executar o metodo SaveChanges passando o paramentro "acceptChangesDuringSave" como false, e manter o SaveChanges(false) para cada url e somente após terminar o processamento voce executara apenas uma vez o AcceptAllChanges.


    Microsoft Community Contributor

    quarta-feira, 17 de abril de 2013 21:04
  • Há duas coleções e seu SaveChange() esta dentro do for q varre a segunda então vc deve fazer o seguinte

    for (int a = 0; a < colunasLinks.Count; a++)
    {
    			//Dessa forma voce vai salva a cada item da colecao colunasLinks, caso queira executar uma unica vez coloca o using pra fora do loop
                    using (smcdbEntities db = new smcdbEntities())
                    {
    				for (int i = 0; i < dtGeral.Rows.Count; i++)
                         await goCrawler(db, url, xPathPreco, xPathKeyword, keyword, dtGeral, i, nomeColunaEspecial_3, nomeColunaEspecial_4, nomeColunaEspecial_6, nomeColunaEspecial_7, encoding);
    
                   
    			//remove ele de dentro do outro metodo
    				 db.SaveChange();   
    				
    				}
    }
    			
    			

    var anucio = db.FirstOrDefault(a=>a.Texto.Contains(nomeCmpaign) && a.Texto.Contains(url));
    anuncio.EmEstoque = (emEstoque == "True" ? "S" : "N");

    quinta-feira, 18 de abril de 2013 03:44