Explicit loading

Данное руководство устарело. Актуальное руководство: Руководство по Entity Framework Core 7

Последнее обновление: 16.11.2020

Explicit loading предполагает явную загрузку данных с помощью метода Load(). Допустим, у нас имеются следующие модели:

public class Company
{
	public int Id { get; set; }
	public string Name { get; set; }
	public List<User> Users { get; set; } = new List<User>();
}

public class User
{
	public int Id { get; set; }
	public string Name { get; set; }

	public int? CompanyId { get; set; }
	public Company Company { get; set; }
}
public class ApplicationContext : DbContext
{
	public DbSet<Company> Companies { get; set; }
	public DbSet<User> Users { get; set; }
	protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
	{
		optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=relationsdb;Trusted_Connection=True;");
	}
}

Загрузим данные по первой компании:

using (ApplicationContext db = new ApplicationContext())
{
	// пересоздадим базу данных
	db.Database.EnsureDeleted();
	db.Database.EnsureCreated();

	// добавляем начальные данные
	Company microsoft = new Company { Name = "Microsoft" };
	Company google = new Company { Name = "Google"};
	db.Companies.AddRange(microsoft, google);


	User tom = new User { Name = "Tom", Company = microsoft };
	User bob = new User { Name = "Bob", Company = google };
	User alice = new User { Name = "Alice", Company = microsoft };
	User kate = new User { Name = "Kate", Company = google };
	db.Users.AddRange(tom, bob, alice, kate);

	db.SaveChanges();
}
using (ApplicationContext db = new ApplicationContext())
{
    Company company = db.Companies.FirstOrDefault();
	db.Users.Where(p=>p.CompanyId==company.Id).Load();
    
	Console.WriteLine($"Company: {company.Name}");
    foreach (var p in company.Users)
        Console.WriteLine($"User: {p.Name}");
}

Выражение db.Users.Where(p=>p.CompanyId==company.Id).Load() загружает всех пользователей в контекст. Подвыражение Where(p=>p.CompanyId==company.Id) означает, что загружаются только те пользователи, у которых свойство CompanyId соответствует свойству Id ранее полученной компании. После этого нам не надо подгружать связанные данные, так как они уже есть в контексте.

Консольный вывод программы:

Company: Microsoft
User: Tom
User: Alice

Важно, что здесь подгружаются только те пользователи, которые непосредственно связаны с компанией. Если нам надо загрузить в контекст вообще все объекты из таблицы Users, то можно было бы использовать следующее выражение db.Users.Load()

Для загрузки связанных данных мы также можем использовать методы Collection() и Reference. Метод Collection применяется, если навигационное свойство представляет коллекцию:

using (ApplicationContext db = new ApplicationContext())
{
    Company company = db.Companies.FirstOrDefault();
	db.Entry(company).Collection(t=>t.Users).Load();
    
	Console.WriteLine($"Company: {company.Name}");
    foreach (var p in company.Users)
        Console.WriteLine($"User: {p.Name}");
}

На уровне базы данных вызов db.Entry(company).Collection(t=>t.Users).Load() будет трансформироваться в следующую команду SQL:

SELECT [u].[Id], [u].[CompanyId], [u].[Name]
FROM [Users] AS [u]
WHERE [u].[CompanyId] = @__p_0

@__p_0 в данном случае это параметр, который представляет id компании и который автоматически передается инфаструктурой EF Core.

Если навигационное свойство представляет одиночный объект, то можно применять метод Reference:

using(ApplicationContext db = new ApplicationContext())
{
    User user = db.Users.FirstOrDefault();	// получаем первого пользователя
    db.Entry(user).Reference(x => x.Company).Load();
    Console.WriteLine($"{user.Name} - {user.Company?.Name}");	// Tom - Microsoft
}

На уровне базы данных этот запрос будет транслироваться в следующую команду sql:

SELECT [c].[Id], [c].[Name]
FROM [Companies] AS [c]
WHERE [c].[Id] = @__p_0

где @__p_0 в данном случае это автоматически передаваемый параметр, который представляет свойство CompanyId выбранного пользователя.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850