Данное руководство устарело. Актуальное руководство: Руководство по Entity Framework Core 7
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 выбранного пользователя.