Здравствуйте!
Есть некая форма, которая отображает набор одних и тех же сущностей в двух видах. Сущности эти из одной и той же таблицы БД. Но для удобства работы заказчик попросил представлять их одновременно на одной форме в виде дерева и в виде таблицы. В таблице на форме находится полный список этих сущностей. В БД есть таблица родитель-потомок для построения дерева этих сущностей. Было принято решение сделать две модели: одну для табличного отображения, другую для дерева. Чтобы не путаться в моделях был сделан класс (ModelHolder), который эти модели инкапсулирует и вызывает методы обновления обоих моделей сразу. Вот тут и возникает вопрос, а где и кто должен вызывать методы обновления БД? Сложность в том, что действия над деревом могут затрагивать изменения в таблице, и наоборот. Получается, что одна модель себя изменила, дальше ей нужно и вызвать методы БД, и изменить другую модель, которая в свою очередь хочет того же! Поулчается такая рекурсия чтоли, из которой я не могу выбраться... Когда речь об одной модели, то тут понятно — она же и дёргает базу. А если речь о двух параллельных моделях, то я теряюсь. Вроде бы дёргать БД можно из ModelHolder, но тогда я эти модели не смогу использовать в таком же виде в других местах, ведь они в таком случае не будут уметь работать с базой. Ещё одно решение — сделать общую модель и для дерева и для таблицы. Тогда всё становиться понятно. ModelHolder не нужен и мы из самой модели вызываем методы БД после обновления модели. Но опять же, эта модель получиться только для этой формы и больше нигде её не удастся использовать. А отдельная модель для таблицы и для дерева будет неоднократно использоваться в проекте. Подскажите пожалуйста, как лучше тут поступить, чтобы потом можно было повторно использовать код этих моделей? Спасибо
Пример с использованием промежуточного класса, который держит обе модели и вызывает обновление данных в БД:
Псевдокод
class ModelHolder
{
ModelTree _mtr = new ModelTree();
ModelTable _mtb = new ModelTable();
DataBaseWorker _dbw = new DataBaseWorker();
public void AddNewElement(object ob)
{
_mtr.AddNew(ob);
_mtb.AddNew(ob);
_dbw.AddNew(ob);
}
}
Здравствуйте, corpse56, Вы писали:
C>Здравствуйте! C>Есть некая форма, которая отображает набор одних и тех же сущностей в двух видах. Сущности эти из одной и той же таблицы БД. Но для удобства работы заказчик попросил представлять их одновременно на одной форме в виде дерева и в виде таблицы. В таблице на форме находится полный список этих сущностей. В БД есть таблица родитель-потомок для построения дерева этих сущностей. Было принято решение сделать две модели: одну для табличного отображения, другую для дерева.
Вот в этот момент вы и встряли. Зачем вам две модели? Роль модели как раз в том и состоит, чтобы обеспечивать согласованное представление данных во всех контролах.
C>Ещё одно решение — сделать общую модель и для дерева и для таблицы. Тогда всё становиться понятно. ModelHolder не нужен и мы из самой модели вызываем методы БД после обновления модели. Но опять же, эта модель получиться только для этой формы и больше нигде её не удастся использовать.
Не очень понятно, почему это её не удастся использовать. Нормальная модель должна давать достаточно информации для биндинга как дерева, так и таблицы.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
S>Вот в этот момент вы и встряли. Зачем вам две модели? Роль модели как раз в том и состоит, чтобы обеспечивать согласованное представление данных во всех контролах.
Ну чтобы по-отдельности их использовать в других местах!
S>Не очень понятно, почему это её не удастся использовать. Нормальная модель должна давать достаточно информации для биндинга как дерева, так и таблицы.
Но если такую модель использовать скажем только для дерева на другой форме, то остальная "табличная" часть этой модели становится не нужна! Вот это и настораживает.
Здравствуйте, corpse56, Вы писали:
C>Здравствуйте! C>Есть некая форма, которая отображает набор одних и тех же сущностей в двух видах. Сущности эти из одной и той же таблицы БД. Но для удобства работы заказчик попросил представлять их одновременно на одной форме в виде дерева и в виде таблицы. В таблице на форме находится полный список этих сущностей. В БД есть таблица родитель-потомок для построения дерева этих сущностей. Было принято решение сделать две модели: одну для табличного отображения, другую для дерева. Чтобы не путаться в моделях был сделан класс (ModelHolder), который эти модели инкапсулирует и вызывает методы обновления обоих моделей сразу. Вот тут и возникает вопрос, а где и кто должен вызывать методы обновления БД? Сложность в том, что действия над деревом могут затрагивать изменения в таблице, и наоборот. Получается, что одна модель себя изменила, дальше ей нужно и вызвать методы БД, и изменить другую модель, которая в свою очередь хочет того же! Поулчается такая рекурсия чтоли, из которой я не могу выбраться... Когда речь об одной модели, то тут понятно — она же и дёргает базу. А если речь о двух параллельных моделях, то я теряюсь. Вроде бы дёргать БД можно из ModelHolder, но тогда я эти модели не смогу использовать в таком же виде в других местах, ведь они в таком случае не будут уметь работать с базой. Ещё одно решение — сделать общую модель и для дерева и для таблицы. Тогда всё становиться понятно. ModelHolder не нужен и мы из самой модели вызываем методы БД после обновления модели. Но опять же, эта модель получиться только для этой формы и больше нигде её не удастся использовать. А отдельная модель для таблицы и для дерева будет неоднократно использоваться в проекте. Подскажите пожалуйста, как лучше тут поступить, чтобы потом можно было повторно использовать код этих моделей? Спасибо
C>Пример с использованием промежуточного класса, который держит обе модели и вызывает обновление данных в БД: C>Псевдокод C>
C>class ModelHolder
C>{
C> ModelTree _mtr = new ModelTree();
C> ModelTable _mtb = new ModelTable();
C> DataBaseWorker _dbw = new DataBaseWorker();
C> public void AddNewElement(object ob)
C> {
C> _mtr.AddNew(ob);
C> _mtb.AddNew(ob);
C> _dbw.AddNew(ob);
C> }
C>}
C>
Здравствуйте, Qulac, Вы писали:
Q>Делал подобное с одной моделью на wpf.
Спасибо за ответ! Вам наверняка, и даже очень может быть в том же проекте, нужна была модель отдельно для табличного представления. Вас не коробило то, что её нужно было заново сделать, а код там практически весь повторяется из "двойной модели"?
Здравствуйте, corpse56, Вы писали:
C>Здравствуйте, Qulac, Вы писали:
Q>>Делал подобное с одной моделью на wpf.
C>Спасибо за ответ! Вам наверняка, и даже очень может быть в том же проекте, нужна была модель отдельно для табличного представления. Вас не коробило то, что её нужно было заново сделать, а код там практически весь повторяется из "двойной модели"?
Нет, у меня там ни чего не повторялось, один объект модели биндился к двум видам: к дереву и таблице.
Здравствуйте, corpse56, Вы писали:
C>Здравствуйте! C>Есть некая форма, которая отображает набор одних и тех же сущностей в двух видах. Сущности эти из одной и той же таблицы БД. ... Было принято решение сделать две модели...
Мне кажется где-то здесь, для начала, вопрос терминологии. Модель — она и есть модель — это та логика которая мало зависит от отображения на форме.
Под ваши требования классически подходит шаблон MVP: 1. Имеем одну модель, которая реализует всю выборку и обработку данных в терминах BLL — DAL, 2. Презентер знает как работать с моделью и отдавать данные view. 3 Две вью выполняют одну и туже функцию, но имею разную внешность (дерево и таблица) — соответственно их можно унаследовать от одного интерфейса (программного интерфейса — ISomeView, не визуального), реализовав нужное отображение. И затем всего лишь отдавать презентеру нужную реализацию.
При определенной реализации тут еще конечно может быть разница в получении данных. Например ModelTree может лениво забирать данные при раскрытии подузлов, а ModelTable — грузить все целиком, либо постранично, либо с виртуализацией — зависит от объема данных. Но эту проблему можно обойти, если сделать слой DAL или BLL достаточно универсально реализующий загрузку данных с кешированием и прочим.
Так что модель должна быть одна. Презентер, скорее всего тоже. А вот вью — сколько угодно.