나는이 수업을 갖는다.
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; }
}
그리고이 2 가지 저장소 메서드가 있습니다.
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();
}
}
이 두 메서드에 대한 LINQ 문을 보면 where 절의 변수 이름과 동일하지만 ID와 동일한 값을 갖습니다.
무슨 일이 일어나고있는 첫 번째 방법 (GetById), LINQ 쿼리 후, 그 자식 GetChildren 호출 안에 이유가 null입니다.
그러나 두 번째 방법 (Update)에서 LINQ 쿼리 후에 반환 된 개체의 자식이 모두 있습니다. 그들은 동일한 질의이고 동일한 값을 가지고 있는지 확인하기 위해 반복적으로 점검했습니다.
이 호출을하기 전에 특별한 사전 코드가 없습니다. 그들은 단지 정상적으로 호출됩니다. 그래서 나는이 행동에 대해 정말로 혼란스러워합니다. 무엇이 이것을 일으킬 수 있습니까?
첫째, EF Core는 관련 엔티티를 자동으로 포함 하지 않습니다 . EF Core는 지연로드를 지원하지 않으므로 모든 관련 엔티티를 열거하여 ( Include
통해)로드하거나 명시 적으로로드해야합니다 ( Load
).
즉, EF의 DbContext는 개체 그래프를 유지 관리하며 개체가 쿼리 될 때 해당 그래프에 유지됩니다. 일단 자식이로드 되면 EF는 DB에서 쿼리하지 않고 그래프에서 해당 엔티티를 다시 설정할 수 있습니다. 그러나, 이것은 당신이 의지해야하는 것이 아닙니다. 매우 많은 피해를 입었습니다. 당신은 근본적으로이 방법이 작동했던 특정 순서로 호출 된 것을 운이 좋았습니다. 사물이 거기에 있지 않을 것이라고 가정하고 그에 따라 행동하는 것이 항상 최선입니다. EF가 실제로 쿼리를 발행 할 필요가 없다면, 훌륭하지만, 필요할 경우 권한을 부여 받아야합니다.