|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Коллеги, приветствую! Посмотрел на YT несколько курсов лекций по теме, прочитал нескоько статей на Хабре и тематических ресурсах, но так и не принял для себя решение по деталям реализации осваиваемого мной ныне MVVM в разрабатываемом приложении. Задача : Нужно носимое приложение с минимальным количеством DLL в папке приложения. В этой же папке должен быть каталог с БД приложения. Интерфейс требуется сделать не-примитивным (подробнее - ниже), коим почти все обучающие примеры MVVM обладают. Данных будет не очень много (в пределах 30 МБ текста за год). Решение : NET Core 3 приложение на C# с использованием WPF. БД на этапе разработки - файлы JSON, одна таблица БД - один файл. От SQLite+EF отказался на этом этапе как раз из-за того, что они тянут в папку приложения кучу библиотек. Подозреваю, это количество можно сильно уменьшить, но пока не знаю как. Детали : 1. Набор таблиц не на 100% соответствует набору классов бизнес-модели (есть "промежуточные" таблицы для связи многие-ко-многим, а "бизнес-классов" для них, понятно, нет). Из-за предстоящего возможного перехода на другой (или дополнительный) способ хранения данных хочу отделить бизнес-модель от модели данных. Сейчас есть: Model\DataContext - бизнес-модель; набор интерфейсов, на которые буду ссылаться во ViewModel. Например: IBuilding; IRoom; ISubject; Model\Json - модель данных JSON; набор класов, которые воспроизводят структуру БД и реализуют интерфейсы бизнес-модели. Например: JsonContext { GetBuildings(), SaveBuildings(), etc } DbRecord { ID, IsArchive, DateModified }; Building : DbRecord, IBuilding; Room : DbRecord, IRoom; Subject : DbRecord, ISubject; В перспективе вместо или в довесок к Model\Json может появиться Model\Excel, Model\SQLite, Model\Web и т.п. Таким образом, какие-то бизнес-объекты будут получать и сохранять данные не в Json, а в других хранилищах. Будет ли такое, что, например, объекты IBuilding будут загружаться частично из Json и частично из SQLite - не знаю пока. Скорее всего, нет. Т.е. источник данных для одного типа объектов только один. Оптимально ли так реализовывать модели? 2. Где при такой реализации моделей надо держать экземпляры коллекций записей? К которым (коллекциям) биндятся элементы View. 3. Как корректно реализовать механизмы обработки изменений и сохранения записей, если требуется, чтобы только нажатием кнопки "Сохранить" можно было фиксировать изменения в хранилищах и в других окнах? Насколько я понимаю биндинг, это проблемно, т.к. например: • Есть ListView с записями. Записи - из DataContext'ной коллекции, которая находится - где? (см. вопрос 2) • Кликаем по записи дважды • Открывается окно редактирования записи, DataContext'ом которого (окна) является ссылка на одну из записей коллекции. • Вносим изменения в TextBox'ы. Учитывая биндинги, эти изменения сразу применяются к DataContext'ной записи, а значит и в общюю коллекцию записей. Т.е. нажатие тут кнопки Отмена, закрывающей окно редактирования, не приводит к игнору/отмене изменений, произошедших в этом окне. 4. Как можно подтягиваемые студией библиотеки зависимостей сложить в подпапку, а не чтобы они рядом с выходным exe лежали? VS Community 2019 Ваяю: MSA 2003, mdb | VB.NET + mdb/SQL Express | 1Сv8, ТК УП | C# + FDB ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:58 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
И по поводу интерфейса. Вот так (схематично) предполагается его реализация. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 14:48 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Батюшки, сколько ж опечаток я допустил в первом сообщении... Ууу, позорище! ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 15:01 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
если есть необходимость сделать при минимуме DLL, то их всех можно просто упаковать внутрь EXE как ресурсы и подгружать по требованию и пользоваться всеми библиотеками нормально ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:17 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Roman Mejtes если есть необходимость сделать при минимуме DLL, то их всех можно просто упаковать внутрь EXE как ресурсы и подгружать по требованию и пользоваться всеми библиотеками нормально Об этом был как раз один из вопросов. Как это сделать с помощью VS Community 2019? Как гуглить? EDIT: Видимо, это Спасибо! Остальные вопросы всё же актуальны. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:24 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
изменения должны храниться во ViewModel и при нажатии на кнопку сохраняться в объекты модели тут главное не лениться и разделять объекты модели и модели представления в разные типы :) ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:24 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
гуглить по ключевым словам ResolveAssembly EmbeddedResource https://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource где то у меня были инструкции по импорту библиотек в компилируемый файл для сценариев msbuild, но мне сейчас лень искать. И это не избавляет от необходимости добавлять обработчик к AddDomain.ResolveAssembly. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:29 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Roman Mejtes изменения должны храниться во ViewModel и при нажатии на кнопку сохраняться в объекты модели тут главное не лениться и разделять объекты модели и модели представления в разные типы :) Как я понял этот ответ: экземлпяр коллекции ObservableCollection<IBuilding> для MainWindow должен лежать в MainWindowViewModel. Так? Как тогда бороться с автоматическим обновлением записей этой коллекции тогда, когда это обновление не подтверждено пользователем? Т.е. я открываю BuildingWindow; в его DataContext ссылаюсь на IBuilding в BuildingWindowViewModel и биндю поля формы BuildingWindow на свойства IBuilding - таким образом поля формы сразу же заполняются из записи коллекции. Далее, изменяя текст в полях, я получаю одновременное изменение этой записи в коллекции, что мне НЕ нужно, т.к. в коллекции я хотел бы отражать изменения только при нажатии кнопки ОК в BuildingWindow. Надо, видимо, биндиться на копию записи коллекции? Но тут возникает вопрос про копирование ещё и всех записей IRoom, вложенных в этот IBuilding... EDIT: Ой, по-моему, я путаю сейчас коллекцию во вью-модели с коллекцией в модели (не в БД, а в памяти)... Если так (путаю), то возникает другой вопрос - про рассинхрон этих двух коллекций. Пользователь внёс изменения в форме редактирования записи - они по биндингам попали в запись коллекции вью-модели. Далее он нажал Отмену - и теперь мы имеем запись в коллекции вью-модели, отличающуюся от записи в коллекции бизнес-модели. Или бизнес-модель не должна иметь свой экземпляр, загруженный одновременно (параллельно) с экземпляром вью-модели? И как нам в случае отмены изменений в форме редактирования вернуть запись в ObservableCollection в исходное состояние? Только перечитать из БД/JSON, принуждая MainView обновиться? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:41 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Roman Mejtes гуглить по ключевым словам ResolveAssembly EmbeddedResource Ради б-га, не надо изобретать велосипед. Fody + Costura.Fody . Всё, что требуется - поставить из нугета 2 пакета, и слегка отредактировать FodyWeavers.xml. КириллН Как можно подтягиваемые студией библиотеки зависимостей сложить в подпапку, а не чтобы они рядом с выходным exe лежали? В конец .csproj руками добавить Код: xml 1. 2. 3. 4. 5. 6.
- файлы с масками, перечисленными в тэге MoveToLibFolder, будут после сборки перемещены в папку $(OutputPath)lib. Только при этом надо ещё в конфиге указать probingPath: Код: xml 1. 2. 3. 4. 5.
- иначе сборки не будут найдены. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:07 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН , вы не хотите использовать SQLite+EF. А какая есть альтернатива? JSON и XML удобны только в случае небольшого количество данных. У вас ежегодное накопление - 30 Мб. На мой взгляд, это для XML и JSOM очень много. Это же последовательные файлы. И для работы с ними их придётся скачивать целиком в память. Самый удобный способ работы с ними это сериализация/десериализация. Но как быстро это будет для файлов размером 30-60-150-300 Мб? Второй вопрос - это сохранение. Если изменится хоть один символ XML(JSON) файл надо создавать полностью новый. Изменить что-то в существующем практически невозможно. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:10 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Eld Hasp КириллН , вы не хотите использовать SQLite+EF. А какая есть альтернатива? JSON и XML удобны только в случае небольшого количество данных. У вас ежегодное накопление - 30 Мб. На мой взгляд, это для XML и JSOM очень много. Это же последовательные файлы. И для работы с ними их придётся скачивать целиком в память. Самый удобный способ работы с ними это сериализация/десериализация. Но как быстро это будет для файлов размером 30-60-150-300 Мб? Второй вопрос - это сохранение. Если изменится хоть один символ XML(JSON) файл надо создавать полностью новый. Изменить что-то в существующем практически невозможно. Я прекрасно отдаю себе отчёт в этом и согласен с вами. Смысл этого "изврата" (использование JSON как хранилище на этапе разработки и на первых порах эксплуатации) - это как раз заставить себя понять, как пользовать MVVM в условиях разнородных/изменяющихся источников данных. Мной лично уже выпущено немало приложений на разных языках и разных масштабов: моды, плагины, утилиты, носимые программы, клиент-серверные и веб-решения корпоративного/муниципального/регионального уровня, но я самоучка, пишу код редко и отстаю от мейнстримов. Мне очень-очень хочется разобраться с этим паттерном, но академически я не умею учиться - только под реальный проект. Благо сейчас появился небольшой реальный проект с несжатыми сроками, в рамках которого я могу сделать правильно, "по науке", освоив популярный паттерн. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:22 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН , Ok! MVVM с учётом внешнего хранения данных, дополнится ещё репозиторием. И по моему опыту общения, начинающим гораздо понятнее и удобнее делать реализацию приложения в таком порядке: Репозиторий, Модель, View, ViewModel. Каждый из этих слоёв создаётся в отдельном проекте. Плюс к ним, как минимум, ещё один проект общей библиотеки. Поэтому советую начать с Репозитория. А так как у вас возможно изменение хранилища, то лучше сначала задать интерфейс Репозитория и потом уже делать его реализацию. Интерфейс объявляется в общей библиотеке. В нём должны быть все необходимые для работы с хранилищем методы. Методы в параметрах должны получать либо типы значений, либо ссылочные иммутабельные типы. Очень часто используются иммутабельные DTO. Все кастомные типы также объявляются в библиотеке. Сам репозиторий (для XML или JSON) удобнее начинать создавать с образцового файла данных. Потом по нему создаются классы для сериализации. В репозитории методы сохранения/загрузки сериализует/десериализует этот файл. Модель получает в конструкторе Репозиторий и реализует всю Бизнес Логику (кроме работы с хранилищем). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 22:48 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Eld Hasp, спасибо огромное за развёрнутый ответ! Правильно ли я понял архитектуру решения (см.картинку)? И мне не вполне понятно про "общую библиотеку". ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 12:05 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
ViewModel не должна содержать импорт типов из View, за редким исключением ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 12:20 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Roman Mejtes ViewModel не должна содержать импорт типов из View, за редким исключением Роман, как тогда правильно открывать новые окна и передавать в них объекты в качестве DataContext, а также получать обратно результат работы (Ок, Отмена, выбранный элемент списка...)? В CodeBehind окон View? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 12:47 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Хм... В Repo ещё должен быть "using Model", иначе Repo не будет знать о бизнес-интерфейсах из Model, которые должны быть реализованы в Data-классах Repo. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 16:24 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН , несколько ссылок. Может пригодятся. Структура WPF решения Структура WPF+БД решения Потоки в асинхронном MVVM ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 16:26 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН , в Модели не должно быть ссылки на Репозиторий. Вы же предполагаете возможную замену Репозитория, поэтому Модель "знает" о Репозитории только его интерфейс. Интерфейс содержится в отдельной общей библиотеке. При запуске приложения конкретный репозиторий создаст App и передаст в конструктор Модели по интерфейсу. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 16:31 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
Eld Hasp, снова благодарю за полезные ссылки. Eld HaspКириллН, в Модели не должно быть ссылки на Репозиторий. Вы же предполагаете возможную замену Репозитория, поэтому Модель "знает" о Репозитории только его интерфейс. Эти мои выводы сделаны на основании рассуждения - см. картинку. В нём что-то не так? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 17:00 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
...таким образом, при смене слоя Json на слой SQLite надо будет только изменить в Model\DataContext слово Json на слово SQLite, чтобы вместо Json\JsonContext получилось SQLite\SQLiteContext. А если записывать в виде Json\Context то только namespace поменять. А вы предлагаете вариант, при котором не надо вообще ничего в Model менять? Тогда я недопонял, как это сделать. Пошёл по предоставленным ссылкам... ... |
|||
:
Нравится:
Не нравится:
|
|||
17.03.2021, 17:22 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН ...таким образом, при смене слоя Json на слой SQLite надо будет только изменить в Model\DataContext слово Json на слово SQLite... Не должно такого быть. Изменение репозитория не должны ни на йоту влиять на Модель. Даже просто вставка незначащего пробела в код - это создание новой сборки. Чтобы потом VM увидела эту новую сборку придётся её тоже пересобирать. А потом и View. Вот и получается, что любое незначительное изменение в репозитории приведёт к пересборке всех связанных сборок, хотя там не было никаких изменений. Если же сборки связанны между собой через интерфейсы лежащие в отдельной общей библиотеке, то такого происходить не будет. Внедрением зависимостей должен заниматься App - это самый верхний слой приложения, который лежит надо всеми и о всех всё знает. Он по сути не входит в MVVM и должен быть в отдельном проекте. Но для проектов "средней руки" так делать неудобно, поэтому такое решение используется редко. Но оно более верное с точки зрения архитектуры приложения. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.03.2021, 01:34 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН Эти мои выводы сделаны на основании рассуждения - см. картинку. В нём что-то не так? К своему рисунку нарисуйте слева на всю высоту сборку общей библиотеки. Все слои ссылаются не на нижележащие на эту общую библиотеку. А на всеми нарисуйте на всю ширину ещё слой App. Он будет ссылать на все слои и на общую библиотеку. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.03.2021, 01:49 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
КириллН, сорри за оффтоп, но в чем вы рисуете такие классные диаграммы? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.03.2021, 11:00 |
|
Реализация MVVM с несколькими разными хранилищами данных
|
|||
---|---|---|---|
#18+
vb_sub КириллН, сорри за оффтоп, но в чем вы рисуете такие классные диаграммы? https://miro.com/ Сам только недавно (на онлайн-собеседовании) про него узнал. Оч понравилось. =) Особенно совместная одновременная работа. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.03.2021, 16:46 |
|
|
Start [/forum/topic.php?fid=21&fpage=1&tid=1440246]: |
0ms |
get settings: |
17ms |
get forum list: |
15ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
63ms |
get topic data: |
9ms |
get forum data: |
1ms |
get page messages: |
568ms |
get tp. blocked users: |
1ms |
others: | 335ms |
total: | 1011ms |
0 / 0 |