Sto usando VisualStudio 2017 con .Net Core 2 e EntityFrameworkCore (v2.0.1). L'applicazione è un'applicazione console che avvia un client MQTT e quindi elabora i messaggi ricevuti, memorizzandoli in un database.
Ogni volta che l'applicazione si avvia e al primo aggiornamento funziona come previsto. Tuttavia su ogni aggiornamento successivo con gli stessi dati (nessuno, uno o più campi vengono modificati), lancia un System.InvalidOperationException con il seguente messaggio:
L'istanza del tipo di entità "Entity1" non può essere tracciata perché un'altra traccia con il valore chiave "[SomeKeyValue]" è già tracciata. Quando si allegano entità esistenti, assicurarsi che sia collegata solo un'istanza di entità con un determinato valore di chiave.
Le entità sono abbastanza semplici, usando solo una relazione uno-a-molti.
Ho anche lo stesso repository utilizzato in una scrittura WebApi nello stesso database, e qui lo stesso codice di aggiornamento funziona come previsto senza errori. Ho collegato l'app della console per utilizzare invece WebApi, e funziona, anche se è esattamente lo stesso repository e database.
Ho provato varie raccomandazioni che ho trovato su internet, che è ad esempio per staccare esplicitamente l'entità, ma nessuna di queste ha funzionato.
L'installazione è la stessa di Asp.Net WebApi, utilizzando l'iniezione delle dipendenze
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
Le relazioni One-To-Many sono configurate in questo modo:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity1>()
.HasOne<Entity2>(di => di.Entity1)
.WithMany(d => d.Entity2)
.HasForeignKey(d => d.Entity1Id);
}
Le entità sono:
public class Entity1: ClientChangeTracker
{
[Key]
public string Id{ get; set; }
public ICollection<Entity2> Entity2{ get; set; }
...
}
public class Entity2: ClientChangeTracker
{
[Key]
public string Id{ get; set; }
public Entity1 Entity1{get; set; }
public string Entity1Id{ get; set; }
...
}
Il codice di repository per l'aggiunta di entità:
public void AddEntity(Entity1 entity1)
{
if (_context.Entity1s.Any(x => x.Id== entity1.Id))
{
_context.Entity1s.Update(entity1).Entity;
}
else
{
_context.Entity1s.Add(entity1).Entity;
}
_context.SaveChanges();
}
Qualcuno ha idea del perché questo sta accadendo e di come può essere risolto?
Sembra che la configurazione di DbContext nel contenitore IoC richieda un passaggio aggiuntivo all'interno di un'applicazione console. Invece di
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
richiede un parametro addizione per specificare ServiceLifetime come Transient:
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Transient);
Questo sembra risolvere il problema.