Есть ли способ в Delphi кэшировать строки master-detail и публиковать как основные, так и дочерние строки одновременно

Я хочу опубликовать в памяти некоторые дочерние строки, а затем условно опубликовать их или не публиковать их в базовой базе данных SQL, в зависимости от того, опубликована или не опубликована родительская строка. Мне не нужен полный ORM, но, может быть, только это:

  1. пользователь нажимает кнопку Добавить врача. Откроется диалоговое окно добавить врача.
  2. прежде чем нажать Ok на Add doctor, в диалоговом окне Add doctor пользователь добавляет одного или нескольких пациентов, которые сохраняются только в памяти.
  3. пользователь нажмите Ok в окне Добавить врача. Теперь все пациенты хранятся, плюс новый врач.
  4. если пользователь нажал кнопку Отмена в окне врача, вся информация о докторе и пациенте отбрасывается.

попробуйте, если хотите, мысленно представить, как вы могли бы сделать это, используя Delphi data aware controls и tadoquery или другие объекты ADO. Если есть не-ADO-конкретный способ сделать это, меня это тоже интересует, я просто бросаю ADO, потому что я использую MS-SQL Сервер и ADO в моих текущих приложениях.

Итак, у предыдущих работодателей, где я работал в течение короткого времени, у них был класс под названием TMasterDetail Это было специально написано, чтобы добавить выше в наборы записей ADO. Иногда это срабатывало, а иногда это не удавалось в некоторых действительно интересных и трудных для исправления способах.

есть ли что-нибудь встроенное в VCL или любой сторонний компонент, который имеет надежный способ выполнения этой техники? Если нет, это то, о чем я говорю выше требуя ОРМ? Я думал, что ORMs считались "плохими" многими людьми, но выше приведен довольно естественный шаблон пользовательского интерфейса, который может возникнуть в миллионах приложений. Если бы я использовал не-ADO не-Delphi-db-dataset стиль работы, вышеизложенное не было бы проблемой практически в любом слое персистентности, который я мог бы написать, и все же, когда базы данных с первичными ключами, которые используют значения идентификаторов для связи основных и подробных строк, попадают в картину, все усложняется.

обновление: В данном случае сделки вряд ли идеальны. (Фиксация / откат-слишком грубый механизм для моих целей.)

1 ответов


вы задаете два отдельных вопроса:

  1. как кэшировать обновления?
  2. как я могу одновременно фиксировать обновления связанных таблиц.

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

обновления пакета ADO

поскольку вы уже заявили, что используете ADO для доступа к данным, это разумный вариант. Вам просто нужно Установите тип LockType в ltBatchOptimistic и CursorType либо ctKeySet или ctStatic перед открытием набора данных. Затем вызовите TADOCustomDataset.UpdateBatch, когда вы будете готовы к фиксации.

Примечание: базовый поставщик OLEDB должен поддерживать пакетные обновления, чтобы воспользоваться этим. Поставщик SQL Server полностью поддерживает это.

Я не знаю другого способа обеспечить связь master / detail при сохранении данные, чем вызывать UpdateBatch последовательно для обоих наборов данных.

Parent.UpdateBatch;
Child.UpdateBatch;

Клиентские Наборы Данных

кэширование данных является одной из основных причин TClientDatasetсуществование и синхронизация отношения master / detail совсем не сложно.

для этого вы определяете отношение master / detail для двух компонентов набора данных как обычно (в вашем случае ADOQuery или ADOTable). Затем создайте один провайдер, и подключить его к мастер dataset. Подключить один TClientDataset к провайдеру, и вы закончили. TClientDatset интерпретирует набор данных detail как вложенное поле набора данных, к которому можно получить доступ и привязать элементы управления data aware, как и к любому другому набору данных.

как только это будет на месте, вы просто позвоните TClientDataset.ApplyUpdates и набор данных клиента позаботится о заказе обновлений для основных / подробных данных правильно.

ORMs

там много что может быть сказал об Ормах. Слишком много, чтобы поместиться в ответ на StackOverflow, поэтому я постараюсь быть кратким.

Ормы получили плохой рэп в последнее время. Некоторые ученые зашли так далеко, что назвали их анти-паттернами. Лично я считаю, что это немного несправедливо. Объектно-реляционное отображение-невероятно сложная проблема для правильного решения. ORMs пытается помочь, абстрагируясь от большой сложности, связанной с передачей данных между реляционной таблицей и экземпляром объекта. Но как с все остальное в разработке программного обеспечения нет серебряных пуль и платформы не исключение.

для простого приложения ввода данных без большого количества бизнес-правил ORM, вероятно, перебор. Но по мере того, как приложение становится все более и более сложным, ORM начинает выглядеть более привлекательным.

в большинстве случаев вы захотите использовать сторонний ORM, а не сворачивать свой собственный. Написание пользовательских ОРМ, который идеально соответствует вашим требованиям, звучит как хорошая идея, и ее легко чтобы начать работу с простыми сопоставлениями, но вы скоро начнете сталкиваться с такими проблемами, как отношения родителя/ребенка, наследование, кэширование и недействительность кэша (поверьте мне, я знаю это по опыту). Сторонние ORMs уже столкнулись с этими проблемами и потратили огромное количество ресурсов на их решение.

со многими ORMs вы торгуете сложностью кода для сложности конфигурации. Большинство из них активно работают над уменьшением конфигурации шаблона, обращаясь к соглашениям и политики. Если вы назовете все свои первичные ключи Id вместо того, чтобы сопоставлять соответствующего Id свойство для каждого класса вы просто говорите ORM об этом соглашении, и он предполагает, что все таблицы и классы его знают о соблюдении соглашения. Вам нужно только переопределить Соглашение для конкретных случаев, когда оно не применяется. Я не знаком со всеми Ормами для Delphi, поэтому я не могу сказать, какие поддерживают это, а какие нет.

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