Использование экземпляра DbContext внутри класса сущности

Недавно я начал изучать Entity Framework Core, и мне любопытно, можно ли использовать экземпляр DbContext внутри класса сущности.

Образец кода:

class User {
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Order> Orders { get; set; }

    public void LoadOrders() {
        using (var context = new StoreContext()) {
            Orders = context.Orders             
                .Where(x => x.UserId == Id)
                .ToList();
        }
    }
}

Сущность пользователя связана с классом Order, у обоих из них есть соответствующие таблицы в базе данных, созданные с помощью миграции из Entity Framework. Цель метода LoadOrders () - просто загрузить связанные сущности для текущего пользователя, когда это необходимо.

Теперь я хотел узнать, верен ли это подход?

Или, может быть, мне всегда следует загружать связанные объекты одновременно с загрузкой родительского объекта? (Например, .Include (). ThenInclude ())

Или, может быть, код метода LoadOrders () должен быть расположен в каком-то дополнительном классе, таком как UserHelper, который будет использоваться вместе с сущностью User.

Думаю, лучший вариант - использовать его в клиентском коде.

Llazar 02.10.2018 21:13

Должно быть действительным. Проблема создания структуры базы данных и чтения / записи в базу данных - это две отдельные проблемы, и их следует рассматривать как таковые для более слабосвязанной конструкции. Если вы хотите протестировать свой код, я бы также предложил вам использовать какой-либо шаблон проектирования, например, на мгновение шаблон репозитория.

i regular 02.10.2018 21:59

На самом деле дизайн, ориентированный на предметную область, рекомендует делать что-то подобное, чтобы избежать «анемичных занятий». Вместо создания экземпляра DbContext попробуйте передать его методу. Загляните в эту статью. thereformedprogrammer.net/…

Mauricio Atanache 03.10.2018 00:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
367
1

Ответы 1

Вам следует избегать использования подобного подхода, потому что пользователь будет загружен одним контекстом DbContext, а его заказы будут связаны с другим удаленным контекстом. Когда вы перейдете к обновлению пользователя, вы столкнетесь с ошибками или дублирующимися заказами, или у вас возникнет беспорядочный бизнес по повторной привязке заказа (и других дочерних сущностей) к контекстам перед сохранением. В дальнейшем, несомненно, возникнет путаница, если заказы привязаны к пользователям, и кто-то пойдет и напишет код в .Include(x => x.Orders). Если вы полностью отсоедините связанные сущности от EF и полагаетесь на нагрузку по запросу, вы потеряете большую часть возможностей, которые дает вам EF. .

Подобные проблемы обычно возникают из-за смешения объема / продолжительности жизни сущностей и контекста, из которого они загружаются. Например, загрузка сущностей одним методом с помощью DbContext, их возврат, а затем решение о том, что вы хотите получить доступ к связанным сущностям, но DbContext был удален. Самый простой метод, который я могу порекомендовать, - это использование моделей представления POCO и обеспечение того, чтобы объекты никогда не выходили из области действия своего DbContext, а только модели представления. Таким образом, вы можете создать структуру модели представления для представления необходимых данных, а затем использовать сущности и их ссылки для заполнения этих моделей представления с помощью .Select(), не беспокоясь о ленивой загрузке или нетерпеливой загрузке.

Например:

using (var context = new StoreContext())
{
  var userViewModel = context.Users.Where(x => x.UserId == userId)
    .Select(x => new UserViewModel 
    {
      UserId = x.UserId,
      UserName = x.UserName,
      Orders = x.Orders
        .Where(o => o.IsActive)
        .Select( o => new OrderViewModel
        {
          OrderId = o.OrderId,
          OrderNumber = o.OrderNumber
          Price = o.OrderItems.Sum(i => i.Price)
        }).ToList()
     }).SingleOrDefault();
   return userViewModel;
}

Automapper может помочь с отображением объектов для просмотра моделей. Это не однозначная карта древовидной структуры, а скорее выравнивание модели представления для представления данных, необходимых представлению, с последующим заполнением их структурой сущности. Вам просто нужно быть немного осторожным, чтобы извлекать только данные и поддерживаемые агрегированные методы из сущностей, потому что они будут переданы в SQL, поэтому никаких .Net или пользовательских функций в .Select. Позвольте моделям представления принимать необработанные значения и предоставлять альтернативные свойства для выполнения форматирования или использовать .Select() для выборки анонимных типов, заставить EF материализовать их в экземпляры POCO с помощью .ToList() / .Single() / и т. д. а затем заполните свои модели представлений из тех, которые используют Linq2Object.

Работа с объектами по запросу и просмотр моделей / DTO для передачи данных позволяет избежать множества проблем с объектами. Если все сделано правильно, EF может извлекать эти данные очень быстро и позволяет избежать проблем с производительностью, таких как отключение ленивых нагрузок во время сериализации. Это означает, что когда вы закончите с моделью представления, вам нужно будет повторно загрузить объект, чтобы применить изменения. Может показаться, что имеет больше смысла просто использовать объекты, а затем EF волшебным образом повторно присоединить их и сохранить изменения, но ваша модель представления будет иметь всю информацию, необходимую для быстрого получения этого объекта по идентификатору, если это необходимо, и вам нужно будет рассмотреть случаи где данные могли измениться между моментом, когда вы впервые получили объект, и временем, когда вы готовы его изменить.

Другие вопросы по теме