Nano Hash - криптовалюты, майнинг, программирование

Linq to Entities & WPF — сохранять только объекты, связанные с представлением

[ОТРЕДАКТИРОВАНО]

Я ищу способ реализовать Linq To Entities в приложении WPF (MVVM) и сделать каждый View (или ViewModel) ответственным за отдельное управление своими базовыми объектами.

Вот пример простой структуры и того, чего я хотел бы достичь:

[Клиенты] (1..1) ‹----> (0..* ) [Заказы] (0..* ) ‹-- [OrderLine] --> (1..* ) [Товар]

Первое представление отображает список клиентов.

  • загружает всех клиентов, но не их заказы
  • позволяет создавать или удалять клиентов

Второе представление отображает сведения о покупателе и список его заказов.

  • позволяет обновить свойства клиента
  • загружает все заказы конкретного клиента, но не строки заказов
  • позволяет создавать или удалять заказы
  • может быть несколько представлений, управляющих отдельно несколькими клиентами.

Третье представление отображает детали заказа и список строк заказа.

  • позволяет обновить свойства заказа
  • загружает все строки заказов определенного заказа, и все продукты, связанные с этими строками заказов
  • позволяет создавать или удалять строки заказов
  • может быть несколько представлений, управляющих отдельно несколькими заказами.

Четвертое представление отображает сведения о продукте.

  • позволяет обновить свойства продукта
  • связанный продукт может быть уже загружен третьим просмотром
  • может быть несколько видов, открытых одновременно и управляющих отдельно своими собственными продуктами. Я не хочу обновлять все продукты сразу, а только связанные продукты в представлении.

Согласно рекомендации Microsoft, должен быть один экземпляр DbContext для каждого экземпляра представления (или экземпляра viewModel) (https://msdn.microsoft.com/en-us/data/jj729737.aspx).

Приведенная выше схема, конечно, очень упрощена. В реальном приложении у нас будет гораздо больше сущностей и представлений. Кроме того, это могут быть разные потоки, в которых открываются представления, что затрудняет определение заранее, какие объекты уже загружены из базы данных при открытии нового представления.

Тем не менее, есть один принцип: представление (или соответствующая ViewModel) должно отвечать за обновление набора сущностей, которые оно отображает, не запрашивая DbContext для обновления сущностей, обрабатываемых другим представлением.

ВОПРОСЫ

  1. DbContext productView должен иметь возможность передавать изменения в связанном продукте в базу данных. Однако он не должен загружать продукт из базы данных, если он уже был загружен ранее (то есть с помощью DbContext, связанного с orderLinesView). Проблема в том, что DbContext, насколько я понимаю, инкапсулирует транзакцию, что заставляет меня думать, что вряд ли он может нести ответственность за сохранение сущностей, которые он не загрузил сам по себе ранее. Как решить такую ​​проблему?

  2. Совершенно очевидно, что у меня должен быть экземпляр DbContext для каждого экземпляра представления, чтобы функция SaveChanges() обрабатывала только данные текущего представления. Что неясно, так это то, что у меня должно быть несколько классов, наследующих DbContext, или один класс, представляющий DbContext приложения.

  3. Нужно ли добавлять свойство DbSet‹> в DbContext для каждого типа объекта, который мы хотим обновить? Похоже, что DbContext нужно будет постоянно менять по мере роста приложения с новыми сущностями. Кроме того, это означает повторяющийся код в моделях представления, чтобы указать, какой DbSet‹> должен быть загружен, и т. д. Не было бы более эффективным иметь механизм (1), который может получать набор сущностей для обновления (независимо от их типа). ) и еще один механизм (2), позволяющий выбрать набор сущностей для передачи механизму (1)? Второй механизм может быть либо ручным (для гибких сценариев), либо автоматическим (например, путем просмотра всех сущностей, перечисленных в ViewModel).

  4. Если я хочу поместить механизм доступа к базе данных в веб-службу, как я могу продолжать управлять их базовыми сущностями каждого представления отдельно? В таком случае, где и как следует создавать экземпляры DbContexts?

Я с нетерпением жду любых советов, которые вы можете дать.


  • Если вы продолжите изменять один и тот же экземпляр объекта, вы сохраните только этот экземпляр. Если вы продолжаете создавать новые экземпляры своих сущностей, а затем добавлять их в контекст, они сохранятся, когда вы вызываете SaveChanges в своем контексте. Вы на самом деле сохраняете дубликаты в своей базе данных в настоящее время, или это теоретический вопрос? 09.03.2015

Ответы:


1

Вы можете реализовать что-то вроде Шаблон единицы работы и репозитория

Таким образом, вы можете сохранить изменения, внесенные в базу данных как часть работы (окно в вашем случае), отдельно от других. Если вы используете один и тот же контекст для всего, это будет сложно.

РЕДАКТИРОВАТЬ: пытаясь ответить на некоторые из ваших вопросов:

1) Пока следующее представление не изменяет объекты из других представлений, вы можете передать ему DTO для логики на них. Однако это может вызвать некоторые проблемы с параллелизмом, если данные, на которых вы основывали свой логин, изменились. Нет простого способа обойти это без сохранения всех связанных сущностей за один раз. Вы можете попытаться создать свой собственный кеш и использовать его вместо запроса DbContext в этих сценариях, но опять же это может быть проблемой для нескольких пользователей.

2 и 3) Взгляните на шаблоны Unit of Work и Repository, о которых я упоминал выше. Это должно сделать хорошую оболочку, чтобы избежать дублирования кода.

4) Для веб-службы вы должны создавать DbContext для каждого запроса, иначе вы можете снова столкнуться с проблемами параллелизма. Наличие кеша здесь также может улучшить производительность.

09.03.2015
  • Хотя добавление дополнительного уровня абстракции с помощью этого шаблона может помочь найти решение вопроса OP, на самом деле это не ответ на заданный вопрос. 09.03.2015
  • Это верно, но я думаю, что проблема связана с тем, что он использует один и тот же экземпляр контекста базы данных для управления объектами из разных окон. Поэтому, когда одно из окон пытается сохранить, оно также сохраняет объекты, измененные другими окнами. Ответ будет таков: не делитесь DbContext, но я подумал, что было бы полезнее указать ему также на хорошо известный шаблон, который решает эту проблему, наряду с другими. 09.03.2015
  • Верно, но если я не правильно понимаю вопрос, это не случай использования нескольких объектов контекста. OP звучит так, как будто они просто добавляют в контекст дополнительные экземпляры объектов сущностей. 09.03.2015
  • Давайте подождем, пока он уточнит, я думаю, что просто каждое представление использует один и тот же контекст. Но я могу ошибаться! 09.03.2015
  • Да, это может пойти в любом случае в зависимости от ответа ОП. Думаю, нам нужно больше информации. 09.03.2015
  • Спасибо вам обоим за ваши ответы. Извините, если я задал тривиальный вопрос, но я новичок в сущностях Linq To. Я думал, что могу иметь только один контекст данных, а затем управлять каждым объектом отдельно, но, если я вас хорошо понимаю, это не работает. Поэтому, скорее, я должен наследовать один класс dbContext для каждого типа окна (например: StudentView‹->StudentDbContext, SchoolView‹->SchoolDbContext и т. д.), создавать новый экземпляр dbContext каждый раз, когда я создаю новое окно, а затем вызывать SaveChanges() & dispose() при закрытии окна. Как только вы подтвердите, что это хорошее решение, я переформулирую свой первый пост. 10.03.2015
  • Вы можете использовать один и тот же класс, просто разные экземпляры для каждого, но это звучит как хороший подход. 10.03.2015
  • Я очень извиняюсь за долгое время без ответа. Пришлось временно покинуть проект. Теперь я обновил свой первый пост, приведя конкретный пример. Было бы неплохо, если бы вы могли взглянуть на него. Спасибо. 05.04.2015
  • Я пытался ответить на ваши вопросы @MaximeMax Дайте мне знать, если вам нужна дополнительная информация об ответах. 07.04.2015
  • Спасибо за ваш ответ. Единственный момент, который я не очень хорошо понимаю, это то, как шаблон единицы работы может помочь в моем случае. Сам dbContext уже является единицей работы, а набор баз данных уже является репозиторием, поэтому я не вижу, как добавление уровня абстракции поможет моему вопросу 2) и 3). 19.04.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..