Entity Framework Core и Lazy Load

210
05 апреля 2018, 11:58

Осваиваю Entity Framework Core, возникло непонимание работы с Navigation Properties и в частности как должна работать Lazy load.

Модель Competition имеет связь многие к одну с моделями: Player (в каждом соревновании по два участника), Arbitor, Tournament.

public class Competition
{
    [Key]
    public int CompetitionID { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public int Player1ID { get; set; }
    [Required]
    public int Player2ID { get; set; }
    [Required]
    public int ArbitorID { get; set; }
    [Required]
    public int TournamentID { get; set; }
    public Result? MatchResult { get; set; }
    public virtual Player Player1 { get; set; }
    public virtual Player Player2 { get; set; } 
    public virtual Arbitor Arbitor { get; set; }
    public virtual Tournament Tournament { get; set; }
}
public class Player 
{
    public int PlayerID { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string Country { get; set; }
    [Required]
    public int Age { get; set; }
    public virtual ICollection<Competition> Player1Competitions { get; set;}
    public virtual ICollection<Competition> Player2Competitions { get; set;}
}
public class Arbitor
{
    [Key]
    public int ArbitorID { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string Country { get; set; }
    [Required]
    public int Seniority { get; set; }
    public virtual ICollection<Competition> Competitions { get; set; }
}

Модель Tournament опущена за ненадобностью при рассмотрении проблемы. Так как Competition имеет два FK Player, явно прописал связи:

protected override void OnModelCreating (ModelBuilder modelBuilder) 
{
        modelBuilder.Entity<Competition> ()
            .HasOne ( m => m.Player1 )
            .WithMany ( n => n.Player1Competitions )
            .HasForeignKey ( m => m.Player1ID );
        modelBuilder.Entity<Competition> ()
            .HasOne ( m => m.Player2 )
            .WithMany ( n => n.Player2Competitions )
            .HasForeignKey ( m => m.Player2ID );
}

Возникшие проблемы:

  1. Насколько я понимаю, обозначая свойство как virtual, мы используем Lazy load. Но тогда почему, если мне нужно получить запись Competition (со всеми свойствами), я должен явно включать каждое свойство:

            var competition = await _context.Competitions
            .Include(c => c.Arbitor)
            .Include(c => c.Player1)
            .Include(c => c.Player2)
            .Include(c => c.Tournament)
            .SingleOrDefaultAsync(m => m.CompetitionID == id);

    Если не прописываю Include, то свойства остаются null. Но ведь они должны подгружаться самостоятельно при ленивой загрузке?

    2.Схожая ситуация с коллекцией объектов, тоже объявленной как virtual. Разве при ленивой загрузке коллекция не должна подгружаться без явного включения? Также насколько я понимаю, при ленивой загрузке вложенные свойства должны также подгружаться (так для каждого Competition должен подгрузиться необходимый Arbitor). Но явно включая коллекцию и проходя по объектам, вложенные свойства остаются равны null. Как в таком случае подгружать все вложенные свойства?

            var player = await _context.Players
            .Include ( s => s.Player1Competitions )
            .Include ( s => s.Player2Competitions )
            .SingleOrDefaultAsync ( m => m.PlayerID == id );
Answer 1

В EF сore фича lazy loading доступна с 2.1

Если очень хочется понять разницу между Eager - Lazy - Implicit, то делайте тренировочные проекты на EF 6.

PS Я лично вообще считаю, что Lazy loading нужно отключить и не включать. Причина проста: явное лучше неявного. Вы можете управлять тем, что подключать и когда подключать, а не тянуть кучу лишнего из базы.

READ ALSO
Настройка проекта Visual Studio 2017

Настройка проекта Visual Studio 2017

При создании проекта на С# студия автоматически вставляет следующий код:

238
свойство enabled пункта контекстного меню для разных gridview

свойство enabled пункта контекстного меню для разных gridview

В форме есть grdControl1 и gridview1 и gridview2Имеется контекстное меню с пунктом "Подробно"

219
Использование Lazy Loading

Использование Lazy Loading

Пробую использовать lazy loading entityframeworkСмотрю примеры с метанита

261
Сообщает ли MongoDB о расположении Master

Сообщает ли MongoDB о расположении Master

На сколько мне известно, запись ведется только через Master, а чтение возможно и из SlaveОднако встаёт такой вопрос: Если я подключился к Slave и знаю...

211