Error writing to Mongodb using C#Parallelism

Asked

Viewed 119 times

2

I have a collection on Mongo that has subdocuments, so I read xml files and write them to Mongodb. Each xml file is a document in Mongo.

My classes

public class Cabecalho
{
    public Cabecalho()
    {
        Operacoes = new List<Operacao>();
    }

    public ObjectId Id { get; set; }
    public Int64 Codigo1 {get; set;}
    public Int64 Codigo2 {get; set;}
    public string Nome { get; set; }
    public List<Operacao> Operacoes { get; set; }
}

public class Operacao
{
    public Operacao()
    {
        Itens = new List<Item>();
    }

    public ObjectId Id { get; set; }
    public string Valor { get; set; }
    public List<Item> Item { get; set; }
}

public class Item
{
    public ObjectId Id { get; set; }
    public string Valor { get; set; }
}

In the Cabecalho class, I used Code 1 and Code 2 to create the document’s input in Mongodb. Code 1 and Code 2 compose the name of the XML file, and since they are all in a single folder there is no possibility of being duplicated.

To write to Mongo I am using the following code:

Recording on the Mongodb

var po = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount > 1 ? Environment.ProcessorCount / 2 : 1 };

Parallel.ForEach(arquivos, po, (arquivo, state) =>
{

    MongoCollection<Cabecalho> auditoriaMongo = MongoConnect.GetLogAuditoria();

            try
            {
                var Cabecalho = new Cabecalho();
                Cabecalho.Nome = @"Valor 1";
                Cabecalho.Codigo1 = arquivo.Name.Split('-').Count() > 1 ? Int64.Parse((arquivo.Name.Split('-')[1]).Replace(".", "")) : 0;
                Cabecalho.Codigo2 = arquivo.Name.Split('-').Count() > 1 ? Int64.Parse((arquivo.Name.Split('-')[2]).Replace(".siag", "")) : 0;

                var body = record.SelectSingleNode("body");
                if (body != null)
                {
                    string[] linhas = body.InnerText.Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var linha in linhas)
                    {
                        string conteudo = linha;
                        var operacao = new Operacao();
                        if (!conteudo.Contains("\t"))
                        {
                            string tipo = conteudo.Substring(0, conteudo.IndexOf(' ')).Trim();
                            string tabela = conteudo.Substring(0, conteudo.IndexOf("Quando:", System.StringComparison.Ordinal)).Trim();
                            operacao.Valor = tabela;
                            conteudo = conteudo.Remove(0, (tabela + " Quando:").Length);

                            Cabecalho.Operacoes.Add(operacao);
                        }
                        else
                        {
                            var item = new Item();
                            string[] campos = conteudo.Split('\t');
                            item.Valor = campos[0];

                            Cabecalho.Operacoes.Last().Itens.Add(item);
                        }
                    }

                    try
                    {
                        auditoriaMongo.Save(Cabecalho);
                    }
                    catch (Exception ex)
                    {
                        //Duplicate Key error show here
                    }
                }
            }
            catch (Exception ex)
            {
                //Log Error Here
            }

});

Note: Please abstract the reading of the file, I put it there just to exemplify.

Complete error:

Erro: WriteConcern detected an error ''. (Response was { "ok" : 1, "code" : 11000, "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: DB.Collection.$Codigo1_1_Codigo1_1  dup key: { : 359922397, : 1217185957 }", "n" : NumberLong(0) })
  • 1

    Apparently the same header is being inserted twice. Already tried to inspect the generated Debug list before inserting?

  • I tried, it only generates the header once. And another, Save() should update the record if it already exists in Mongo.

1 answer

2


Solution

The problem was solved using the techniques of Threadsafe, more specifically using lock.

Example:

object syncLock = new object();

Parallel.Foreach(words, word =>
{
   lock(syncLock)
   {
      //All code here!
   }
});

Browser other questions tagged

You are not signed in. Login or sign up in order to post.