Ho questa classe:
public class Subject
{
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[StringLength(50)]
public string Code { get; set; }
public int LevelId { get; set; }
public int? ParentId { get; set; }
public int Order { get; set; }
[ForeignKey("LevelId")]
public Level Level { get; set; }
[ForeignKey("ParentId")]
public Subject Parent { get; set; }
public ICollection<Subject> Children { get; set; }
[Column(TypeName = "datetime2")]
public DateTime? DeletedAt { get; set; }
}
E poi ho questi due metodi di deposito:
public Subject GetById(int subjectId)
{
var subjectFound = _context.Subjects.Where(subj => subj.Id == subjectId)
.SingleOrDefault();
var subject = _mapper.Map<Subject>(subjectFound);
if (subjectFound != null)
{
subject.Children = GetChildren(subject.Id).ToList();
}
return subject;
}
public void Update(Subject existingSubject)
{
var subjectToUpdate = _context.Subjects.Where(subj => subj.Id == existingSubject.Id)
.SingleOrDefault();
if (subjectToUpdate != null)
{
_mapper.Map(existingSubject, subjectToUpdate);
_context.Update(subjectToUpdate);
SaveChildren(subjectToUpdate.Id, existingSubject.LevelId, existingSubject.Children);
_context.SaveChanges();
}
}
Se si guardano le istruzioni LINQ per questi 2 metodi, sono gli stessi nomi di variabili diversi nella clausola where, ma hanno lo stesso valore che viene cercato per l'Id.
Quello che sta accadendo adesso è nel primo metodo (GetById), dopo la query LINQ, i Bambini sono nulli il motivo per cui ho una chiamata GetChildren al suo interno.
Ma nel secondo metodo (Update), dopo la query LINQ, l'oggetto restituito ha tutti i relativi figli. Sono la stessa query e ho controllato più e più volte per assicurarmi che avessero gli stessi valori e loro lo fanno.
Non ho alcun codice precedente speciale prima della chiamata a questi 2; sono chiamati semplicemente normalmente. Quindi sono davvero confuso da questo comportamento. Che cosa potrebbe causare questo?
Innanzitutto, EF Core non include automaticamente entità correlate. EF Core non supporta il caricamento lento, quindi tutte le entità correlate devono essere caricate con entusiasmo (tramite Include
) o caricate in modo esplicito ( Load
).
Detto questo, DbContext in EF mantiene un oggetto grafico e, mentre gli oggetti vengono interrogati, vengono mantenuti in quel grafico. Una volta che i bambini sono stati caricati una volta , EF può ristabilire di nuovo quelle entità correlate dal grafico, senza dover interrogare il DB, che è probabilmente quello che stai vedendo qui. Tuttavia, questo non è qualcosa su cui dovresti fare affidamento, dato che è molto o meno. In sostanza, sei semplicemente fortunato che i metodi siano stati chiamati in un certo ordine in cui ciò ha funzionato. È sempre meglio presumere che le cose non ci saranno e agiranno di conseguenza. Se EF non ha realmente bisogno di inviare una query per farlo accadere, ottimo, ma dovrebbe essere abilitato a se necessario.