I'm making an application and I use Entity Framework 6 to access SQL Server.
I have the following case, where I want to update the value of two entities:
Socio
- > SocioDireccion
A partner can have many addresses.
First I call this method to read a partner:
public Socio Leer(int id)
{
Socio resultado = null;
using (var context = new BDConectaClubContext())
{
context.Configuration.LazyLoadingEnabled = false;
context.Configuration.ProxyCreationEnabled = false;
//Usando Include linq lambda
resultado = context.Socio
.Include(s => s.CuentaBancaria)
.Include(s=> s.Direcciones)
.Include(s=>s.EMails)
.Include(s=>s.Grupos)
.Include(s=>s.Vocalias)
.Where(s => s.Id == id).FirstOrDefault<Socio>();
}
return resultado;
}
In the database, the read Partner has only one address. I add two more directions, out of context, since they are disconnected entities, being as follows:
Socio.
----------------
Id
38 (Modificación)
SocioDireccion
---------------
Id Socio_Id
1 38 (Modificación)
0 38 (Alta)
0 38 (Alta)
I call the following method that helps me to add or modify a partner:
public bool Guardar(Socio socio)
{
int r;
using (var ctx = new BDConectaClubContext())
{
ctx.Configuration.ProxyCreationEnabled = false;
ctx.Configuration.LazyLoadingEnabled = false;
// Alta funciona correctamente
if (socio.Id == 0)
{
ctx.Entry(socio).State = EntityState.Added;
foreach (SocioDireccion d in socio.Direcciones)
{
ctx.Entry(d).State = EntityState.Added;
}
r = ctx.SaveChanges();
}
else
{
//Aquí se produce el error
ctx.Entry(socio).State = EntityState.Modified;
foreach (SocioDireccion d in socio.Direcciones)
{
if (d.Id == 0)
ctx.Entry(d).State = EntityState.Added;
else
ctx.Entry(d).State = EntityState.Modified;
}
r = ctx.SaveChanges();
}
return r > 0;
}
}
When this line is running
ctx.Entry(socio).State = EntityState.Modified;
... the following error occurs:
Attaching an entity of type 'RMG.ConectaClub.Models.SocioDirection' failed because another entity of the same type has already 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.
The funny thing is that if I just add a new address to SocioDireccion
the error does not occur and the modification works correctly:
Socio
-------
Id
38 (Modificación)
SocioDireccion
---------------------
Id Socio_Id
1 38 (Modificación)
0 38 (Alta)
With only one new address the error does not occur. If there is more than one, the error occurs.
I've done a simple example so you can see how I add the information to the entities:
private void button1_Click_1(object sender, EventArgs e)
{
//Crear un nuevo socio llamada Pepe con una direccion a
Socio s = new Socio();
s.Nombre = "Pepe";
SocioDireccion direccion = new SocioDireccion();
direccion.Direccion = "calle a";
direccion.Socio = s;
s.Direcciones.Add(direccion);
new FachadaSocio().Guardar(s);
//Leer el socio Pepe y crear dos direcciones a y b
Socio nuevoSocio = new FachadaSocio().Leer(s.Id);
SocioDireccion dir;
dir = new SocioDireccion();
dir.Direccion = "calle b";
dir.Socio = nuevoSocio;
nuevoSocio.Direcciones.Add(dir);
dir = new SocioDireccion();
dir.Direccion = "calle c";
dir.Socio = nuevoSocio;
nuevoSocio.Direcciones.Add(dir);
// El socio Pepe tiene 3 direcciones a,b,c
new FachadaSocio().Guardar(nuevoSocio);
}
I add more information:
The error may be related to this that I have detected. Can you tell me if it's working correctly?
I go through the list of addresses. When an address has the Id=0
, I change the state to Added
. But you can see, when doing an inspection, that I have added all the other entities of Addresses and also the entity Partner.
foreach (SocioDireccion d in socio.Direcciones)
{
estadoDireccion = ctx.Entry(d).State;
if (d.Id == 0)
// Al ejecutar esta instrucción añade el resto de Direcciones y la entidad Socio.
ctx.Entry(d).State = EntityState.Added;
else
ctx.Entry(d).State = EntityState.Modified;
}
ctx.Entry(d).State = EntityState.Added;
adds the entire address list to the context and also adds the Partner to the context.
Acts exactly as if you were adding a parent entity that adds all the daughters with the added state.
Any ideas? Thank you very much for your answers.