EDIT: La risposta è semplice, ho perso la proprietà {get; set} sul mio Timestamp, quindi EF Core ignora la mappatura. Ma continua a leggere se ti senti così incline.
Sto usando InMemoryDatabase di C # EF Core per fare test unitari per la mia applicazione. Tuttavia, per un particolare set di test ho un bizzarro bug in cui il DateTime su alcune entità viene ripristinato al valore predefinito [1/1/0001 12:00:00 AM]
quando li faccio riferimento più tardi.
Questo è l'oggetto POCO che viene creato e aggiunto al contesto:
public class Meter
{
[Key]
public long Id { get; set; }
public DateTime Timestamp;
public int Change { get; set; }
}
E qui è dove viene aggiunto al DbContext:
options = new DbContextOptionsBuilder().UseInMemoryDatabase("TestDB");
using (var db = new CustomContext(options))
{
for (int i = 0; i < 10; i++)
{
var meter = new Meter {Timestamp = new DateTime(2019, 1, 20), Change = i};
db.Meters.Add(meter);
}
db.SaveChanges();
}
Se ho un breakpoint durante il test subito dopo la db.SaveChanges()
, posso vedere che i contatori sono stati aggiunti al Meters DbSet e che hanno il giusto DateTime per il Timestamp (cioè [1/20/2019 12:00:00 AM]
). Tuttavia, quando faccio riferimento al contesto più tardi in questo modo:
using (var db = new CustomContext(options)) //Same options as I used before
{
var times = db.Meters.Select(m => m.Timestamp);
}
Se il punto di interruzione su questa linea, ogni contatore di db.Meters è stato impostato sull'ora di inizio predefinita di [1/1/0001 12:00:00 AM]
. Tuttavia, la proprietà Change
conserva ancora il valore int originale come previsto.
Questo mi sta facendo perdere la testa e ho provato diverse opzioni per correggere il problema. Ho provato ad aggiungere un passaggio intermedio tra l'aggiunta e l'esecuzione delle query, dove eseguivo l'iterazione su ogni contatore e aggiorno il Timestamp, salvando le modifiche e quindi eseguendo una query in un secondo momento, e ancora non funzionava! Ho provato DateTime? Timestamp
e che imposta solo il tempo su null, ho provato anche ad aggiungere [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
come quello che ha aiutato quando si utilizza il mio database Npgsql e gli viene detto di usare CURRENT_TIMESTAMP se Timestamp è mai impostato su null. Mi rendo conto che non ho detto al database InMemory cosa fare con i valori nulli, ma non ho mai dato valori null, quindi cosa dà?
C'è qualche impostazione che ho bisogno di impostare per mantenere InMemoryDatabase da toccare i valori dopo che sono stati impostati?
Il problema non ha nulla in comune con il database InMemory.
La causa è un errore banale nella tua entità:
public DateTime Timestamp;
Timestamp
è un campo , quindi non è mappato e non memorizzato. Mentre si lavora con il contesto utilizzato per aggiungere entità, il tracker delle modifiche restituisce le istanze originali, ecco perché vedi i valori che hai impostato. Ma una volta creato un nuovo contesto, la query crea nuovi oggetti e, naturalmente, i campi non mappati hanno valori predefiniti.
Basta renderlo proprietà
public DateTime Timestamp { get; set; }