#c# #entity-framework #asp.net-core #lazy-loading #ef-core-2.2
#c# #entity-framework #asp.net-core #отложенная загрузка #ef-core-2.2
Вопрос:
Я создаю соединение с БД следующим образом:
protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
{
optionbuilder.UseLazyLoadingProxies().UseSqlite(@"Data Source=Data.db");
}
И я пытаюсь получить доступ к объекту следующим образом:
public static User GetProfile(int uid)
{
using (Db db = new Db())
{
return db.Users.Include(x => x.Settings).FirstOrDefault(x => x.UserId == uid);
}
}
Пользовательский объект выглядит следующим образом:
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Name { get; set; }
public DateTime? LastUsed{ get; set; }
public virtual Setting Settings { get; set; }
}
но при доступе Users.Settings
он выдает следующую ошибку:
«Ошибка, сгенерированная для предупреждения»Microsoft.EntityFrameworkCore.Инфраструктура.LazyLoadOnDisposedContextWarning: Была предпринята попытка отложенной загрузки навигационного свойства «Настройки» для объекта типа «UserProxy» после удаления связанного DbContext.’. Это исключение может быть подавлено или зарегистрировано путем передачи идентификатора события ‘CoreEventId.LazyLoadOnDisposedContextWarning’ методу ‘ConfigureWarnings’ в ‘DbContext.При настройке’ или ‘AddDbContext’.’
Я понимаю, что это значит, но это противоречит моему пониманию включений и того, как это вызывает нетерпеливую загрузку.
Я понимаю, что при использовании include
и явном доступе к объекту путем вызова FirstOrDefault
eager load связанные объекты должны быть заполнены немедленно без необходимости сохранения открытого подключения к БД; но, по-видимому, это не так.
Каков был бы правильный способ сделать это, не требуя, чтобы база данных оставалась открытой?
Комментарии:
1.
db.Users.FirstOrDefault(x => x.UserId == uid);
Работает ли так, как ожидалось?2. Да, он отлично загружает все напрямую связанные свойства, только когда я пытаюсь получить доступ
.Settings
после включения, генерируется исключение.3. Хорошо!
db.Users.Include(x => x.Settings).FirstOrDefault(x => x.UserId == uid);
Работает ли, как ожидалось, приUseLazyLoadingProxies()
удалении?4. Ага! Быстрая загрузка отлично работает без объявления
UseLazyLoadingProxies()
.5. Похоже, это ошибка в EF Core, вы можете опубликовать проблему здесь: github.com/aspnet/EntityFrameworkCore/issues
Ответ №1:
Auther V, разработчик, работающий над EFC, подтвердил, что это ошибка.
https://github.com/aspnet/EntityFrameworkCore/issues/15170
Документация об этом изменении
Это исправлено в EF Core 3.0.0 RC4, но на момент написания этой статьи недоступно в открытом доступе. Я лично не стал бы предлагать использовать RC4, поскольку он все еще находится в разработке и не очень подходит для общего назначения или производственного использования.
На данный момент вы можете подавить ошибку следующим образом:
protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
{
optionbuilder.UseSqlite(@"Data Source=Data.db").UseLazyLoadingProxies();
optionbuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning));
}
optionbuilder.ConfigureWarnings(w => w.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning));
Строка — это то, что вам нужно.
Но, пожалуйста, имейте в виду, что любое неправильное использование отложенной загрузки также будет проигнорировано, предоставляя варианты с нулевым значением при попытке перемещения объекта для закрытых экземпляров DbContext.