How to insert an existing record in the Entity Framework?

2

At some point in the system some records are selected and must be replicated by changing only one value.

At this point I'm selecting the records that I need to insert:

listaRegistros = listaRegistros .GroupBy(r => r.Id)
                        .Select(grp => grp.First()).ToList();

I then use these records selected above to insert new records into the table:

foreach (var orgao in listaOrgaosASeremAdicionados)
{
    foreach (var registro in listaRegistros)
        registro.Orgao = orgao;
    new RegistrosMeService().InsertListaRegistrosMe(listaRegistros);
}

Here is the InsertListaRegistrosMe of class RegistrosMeService :

protected EFSpecificRepository<TB_RegistrosMe, Entities> _repository;
protected EFSpecificRepository<TB_RegistrosMe, Entities> Repository
{
    get
    {
        if (_repository == null)
            _repository = new EFSpecificRepository<TB_RegistrosMe, Entities>();
        return _repository;
    }
}

public int InsertListaRegistrosMe(List<TB_RegistrosMe> listaMe)
{
    Repository.InsertList(listaMe);
    Repository.SaveChanges();
}

The first loop , where the insertion is done, is to inform for how many organs the list of records will be added, more than one may have been selected.

The only change made to the registry is the one that can be checked in loop , which is the change of registro.Orgao .

The problem is that in Insert the error occurs:

  

"An object with the same key already exists in the ObjectStateManager.   is in the Unchanged state. An object can only be added   objectStateManager if it is in the added state. "

I have tried to change the Id, but when trying to do this also an error occurs:

  

The 'Id' property is part of the object's key information and does not   can be modified.

So I understand this problem occurs because I am observing a record that already exists in EF and for security it does not allow me to add this record because it considers it to be duplicate, correct?

But how could I solve this without having to create a new object in EF 3.5 (v1)? Is it possible to change the ObjectStateManager so that it allows me to insert?

    
asked by anonymous 15.05.2017 / 15:11

3 answers

3

If the record needs to be replicated, that is, reinserted, you can not re-enter with the same primary key value. You need to create new objects from objects that already exist. That is:

var novaListaDeRegistros = new List<Registro>();

foreach (var orgao in listaOrgaosASeremAdicionados)
{
    foreach (var registro in listaRegistros) 
    {
        novaListaDeRegistros.Add(new Registro 
        {
            // Coloque aqui todas as propriedades de Registro, 
            // com exceção do RegistroId, que será novo.
            registro.Orgao = orgao;
        });
    }
}

new RegistrosMeService().InsertListaRegistrosMe(novaListaDeRegistros);

PS: Get rid of this repository .

    
15.05.2017 / 16:14
3
The Entity Framework works with observable collections, that is, the records that are returned from your query are being "observed" by the context so that when (and if) changes can be reflected in the database.

Using the AsNoTracking() method should resolve. This method "warns" the context that it is not necessary to observe changes in entities.

listaRegistros = listaRegistros.GroupBy(r => r.Id)
                    .Select(grp => grp.First()).AsNoTracking().ToList();
    
15.05.2017 / 15:18
3

You have two alternatives.

Healthy alternative: clone the objects you want to copy and save the clones. The advantage is that anyone reading your code for maintenance will understand that it was clearly their intention to have new objects. I say this because by reading the code you posted without considering the context of the question, I would swear by my soul and my mother that you mistook the terms insert and update and that your intention was actually to edit existing records in the database instead of inserting new ones.

When you insert a completely new object into the repository, it is marked as a new object in the EF internal collections. When the context is saved the new objects will be inserted into the database.

McGyver Way: This way is very ugly. Seriously. If you do it on purpose I'll find out who you are just to make sure I will never shake your hand. I'm going to add this form here for educational reasons because a lot of people do this unwittingly when they start working with Entity Framework together with ASP.NET .

Simply load objects into a context. Close the context. Now open another context, add the objects and save. The new context will understand that objects are new (since they have not been observed during their retrieval) and will tag all of them for creation in the database.

Most people when they start with ASP.NET do not realize that you have a different context for each page request. People load objects into a GET request and change them in the processing of a POST request. This has already led to pages and question and answer pages in Stack Overflow on object duplication when using the Entity Framework. For most people this is a defect, but it seems that in your case it may be a feature

15.05.2017 / 16:03