Problem changing entity with E.F and Dapper

Asked

Viewed 154 times

1

I have a Dapper query, where I search for an entity:

var fatura = ObterPorClientedEDataVencimento(cobranca.ClienteId, cobranca.DataCobranca);

The method and properties of my entity are in this Gist, I put there just so the question doesn’t get too long. https://gist.github.com/Renancp01/66e5d10a66c97b1bf791bae044bffdab

Which brings the data in normally. However, when I try to change this entity, I have the error:

Attaching an Entity of type 'Paguela.Gateway.Domain.Entities.Invoice' failed because Another Entity of the same type already has the same Primary key value. This can happen when using the 'Attach' method or Setting the state of an Entity to 'Unchanged' or 'Modified' if any entities in the Graph have Conflicting key values. This may be because some entities are new and have not yet Received database-generated key values. In this case use the 'Add' method or the 'Added' Entity state to track the Graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.", "Exceptiontype": "System.Invalidoperationexception

From what I understood from the error, the E.F did not "detect" that I am trying to make a change, even setting the Status of the entity as Modified, and tries to add it again, but the Id already exists in the database. Follow my method below for a better understanding of the problem:

cobranca.FaturaId = fatura.FaturaId;
fatura.Valor += cobranca.Valor;
_cobrancaRepository.Atualizar(cobranca);
Db.Entry(fatura).State = EntityState.Modified;

I did a test taking the ID invoice, Dapper query and Obtenporid with E.F and error does not happen.

//Isso Funciona
var fatura = ObterPorClientedEDataVencimento(cobranca.ClienteId, cobranca.DataCobranca);
if (fatura != null)
fatura = ObterPorId(fatura.FaturaId.Value);

Inside I have some questions.

Why does that happen?

How can I use E.F to work with Dapper in this scenario?

How best to solve this problem?

  • you could show the code of your method ObterPorClientedEDataVencimento, I believe the problem is in it, because probably you may have disabled the entity tracker. Also show the entity code

  • @Rodrigok. B put them in a Gist not to get too extensive the question.

  • @Rodrigok. B How I Enable the Entity Trakcer?

  • Numca I needed to use this Querymultiple, so I can’t tell you if it’s correct, but when I looked at your entity I saw that you put the invoice id as an overridable, I think that might be the problem. public Guid? FaturaId { get; set; }

  • That sounds like a scam. What it seems is that you have an entity that is already in context and is trying to attach it again... but with what you have here not give to know.

  • About your question to enable the tracker, actually it is default, but when we do a query we can disable, if this query is for query only, or if the objects will not be modified. This makes the EF more agile. maybe this method of Querymultiple, disable the tracker.

  • @Marconciliosouza Certo, that’s why the questions at the end. I’m trying to understand the problem, and looking for the best way to solve. Actually I don’t have the entity in context, so doing the ObterPorId I bring it into context, and I can change it. Your comment adds nothing to the question, but still thank you for reading it, at least.

  • A question, this Connection you are using, is created by var cn = Db.Database.Connection, this Db is the EF context?

  • @Rodrigok. B For queries, I use only the Dapper

  • I had to have thought about it before, the problem is that you are bringing an entity out of the EF context, so it can not do the entity tracker, it is the tracker that defines the state of the entity. Maybe you could do just "Add", using this model you introduced to us.

  • @Connection ... you need to understand the concept of EF in relation to object mapping ... see what your error says. failed because Another Entity of the same type already has the same Primary key value.... that is already in the context... this solves your problem https://stackoverflow.com/a/44836770/2740371

  • Perfect the observation of @Marconciliosouza, tank that the message that occurred, was the fact that as EF failed to identify the state of the entity, he tried to make an "Add" of the entity, even if you set the state as "Modified".

  • @Rodrigok. B Marconciliosouza It is in question, that when I do the Obtenpeloid by the E.F, the problem does not happen. The problem is that the queries are not made by E.F, but by Dapper, what I’m looking for is a way to solve by making the query by Dapper.

  • But Obtenporid, you are using Dapper too, in question you said you used EF to do it. If you can publish the function.

  • @Rodrigok. B This Obtenporid I did is just a test to identify the problem. And it’s done with using E.F

  • So when you do this using EF, the entity’s traker is happening, because the entity is in context, so it worked. Even if Id sees it from a Dapper query. In short, I find it impossible that a returned entity outside the EF context, it is possible to do what you want.

Show 11 more comments

1 answer

1

Your problem is that the Dapper query is outside the EF context, so you cannot modify the entity.

The error occurred because when trying to set the state of the entity as Modiffied, in the EF Context, because the entity comes from Dapper, the EF wants to add its entity in the database. Then because the ID already exists, the EF returns this error presented in your question.

I see you have two exits.

  1. Change your query to EF, using link basically like this.

    SeuContexto.Set(Fatura).Where(sua consulta aqui);

So all entities returned in this query will be in the EF context, so you can apply CRUD without difficulty.

  1. If you have to keep your Dapper query, every time you need to modify this entity, you should make a query by the ID in the EF, so that this entity is in the context.

Browser other questions tagged

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