Entity Framework - Voce duplicata "1" per la chiave "PRIMARY" "
Utilizzando MySql DB e Entity Framework, quando provo a inserire un dato che contiene un elenco di dati figlio ricevo questo errore: InnerException = {"Duplicate entry '1' for key 'PRIMARY'"}
Ecco un'immagine delle mie tabelle: https://i.stack.imgur.com/bAnVy.png
Questo è il mio modello:
public class Etapa
{
public int Id { get; set; }
public string Descricao { get; set; }
[Column("ativo", TypeName = "bit")]
public bool Ativo { get; set; }
[Column("finalizadora", TypeName = "bit")]
public bool Finalizadora { get; set; }
public List<EtapaVinculada> ListaEtapaVinculada { get; set; }
}
[Table("etapa_vinculada")]
public class EtapaVinculada
{
public int Id { get; set; }
[Column("id_etapa_pai")]
public int EtapaPaiId { get; set; }
public Etapa EtapaPai { get; set; }
[Column("id_etapa_filha")]
public int EtapaFilhaId { get; set; }
public Etapa EtapaFilha { get; set; }
public string Descricao { get; set; }
}
I contesti di Etapa sono qui:
public class ContextoEtapa : Contexto
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Etapa>().HasMany(x => x.ListaEtapaVinculada).WithOne(y => y.EtapaPai).HasForeignKey(x => x.EtapaPaiId);
}
public async Task Adicionar(Etapa registro)
{
await AddAsync(registro);
await SaveChangesAsync();
}
}
Riempiendo manualmente le tabelle nel DB, quando eseguo il debug del mio contesto vedo che il mio oggetto Etapa è riempito e anche la proprietà ListEtapaVinculada è riempita correttamente.
Il problema si verifica quando l'oggetto Etapa riempito con il suo elenco di EtapaVinculada verrà inserito nel database utilizzando il metodo Add. Mi sembra di aver sbagliato una mappatura, perché dà l'impressione che Entity provi a inserire 2x il record Etapa di seguito, cadendo nell'errore di chiave duplicata.
L'incremento automatico sta funzionando. Se provo a salvare un oggetto come questo:
{
Etapa etapa = new Etapa();
etapa.Descricao = "test";
etapa.Ativo = true;
etapa.Finalizadora = true;
etapa.ListaEtapaVinculada = new List<EtapaVinculada>(); // Without itens
using (var context = new ContextoEtapa())
{
await context.Etapa.AddAsync(etapa);
await context.SaveChangesAsync();
}
}
Ma se faccio qualcosa del genere:
{
Etapa etapaFilha = null;
using (var context = new ContextEtapa())
{
etapaFilha = await context.Etapa.Where(x => x.Id == 666).First();
}
Etapa etapa = new Etapa();
etapa.Descricao = "test";
etapa.Ativo = true;
etapa.Finalizadora = true;
etapa.ListaEtapaVinculada = new List<EtapaVinculada>();
EtapaVinculada etapaVinculada = new EtapaVinculada();
etapaVinculada.EtapaPaiId = etapa.Id;
etapaVinculada.EtapaPai = etapa;
etapaVinculada.EtapaFilhaId = etapaFilha.Id;
etapaVinculada.EtapaFilha = etapaFilha;
etapa.listaEtapaVinculada.Add(etapaVinculada);
using (var context = new ContextoEtapa())
{
await context.Etapa.AddAsync(etapa);
await context.SaveChangesAsync();
}
}
Ora ho gli errori della chiave duplicata. Mi sembra che EF stia cercando di inserire un oggetto 2x Etapa, quando il corretto è inserire Etapa, quindi inserire tutti gli itens di ListaEtapaVinculada.
Risposte
Penso che il problema sia quando si tenta di assegnare un'istanza dell'oggetto e un id allo stesso tempo, provare a commentare la seguente riga di codice:
{
Etapa etapaFilha = null;
using (var context = new ContextEtapa())
{
etapaFilha = await context.Etapa.Where(x => x.Id == 666).First();
}
Etapa etapa = new Etapa();
etapa.Descricao = "test";
etapa.Ativo = true;
etapa.Finalizadora = true;
etapa.ListaEtapaVinculada = new List<EtapaVinculada>();
EtapaVinculada etapaVinculada = new EtapaVinculada();
// etapaVinculada.EtapaPaiId = etapa.Id; // this is asigned when asign to collection and savechanges
// etapaVinculada.EtapaPai = etapa;
etapaVinculada.EtapaFilhaId = etapaFilha.Id; //
// etapaVinculada.EtapaFilha = etapaFilha; this is duplicate
etapa.listaEtapaVinculada.Add(etapaVinculada);
using (var context = new ContextoEtapa())
{
await context.Etapa.AddAsync(etapa);
await context.SaveChangesAsync();
}
}