iAlexander |
Отправлено: 26.11.2004, 14:18 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
Привет всем. Заранее извиняюсь за возможное повторение, но найти подобного не смог.
Проблема вот в чем: делаю добавление записи из таблицы (Paradox) следующим способом:
CODE |
ClientQuery->SQL->Clear();
ClientQuery->SQL->Add("SELECT * FROM clients WHERE Num = -1;");
ClientQuery->Open();
ClientQuery->Append();
|
Объясню:
Если не открыть TQuery запрос — Open, то невозможно будет сделать Append.
Для того, чтобы открыть запрос, пишу строку запроса, которая явно ничего не вернет (чтобы не тратить ресурсы)
После этих манипуляций можно редактировать поля записи, а для сохранения делаю ClientQuery->UpdateObject->Apply(ukInsert)
Свойства ClientQuery:
CachedUpdate = true;
RequestLive = false;
Работает. Прилично. Но:
после ClientQuery->Open()
в каталоге программы появляется файл Del2.MB размером 4096 байт, заполненный почти сплошь нулями (только первая сотня немного содержит данные). Либо DEL15.MB, ... Короче, DELxx.MB.
При некорректном завершении программы он остается.
А удаляется после ClientQuery->Close().
В чем причина возникновения этого файла и можно ли ее устранить? |
|
Gedeon |
Отправлено: 26.11.2004, 14:34 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Я маленько не в тему, но нахера Вам, извините, Query, да еще и Open, если Вам не надо возвращать заведомо ни одной записи? Используйте для вставки записи(ей) инструкцию ISERT языка SQL. И юзайте для этого метод ExecSQL TQuery или компонент StoredProcudure, в ADO есть еще такой CommandText.
|
|
iAlexander |
Отправлено: 26.11.2004, 15:21 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
"Нахера" — это что-то новенькое. Раньше я такого не встречал. Извиняю, однако...
Объясняю:
для единства интерфейса для трех операций (добавление, просмотр, редактирование) используется один TQuery c TDataSource и Контролами.
В зависимости от вида операции над этим Query и производится то или иное действие:
1) Open(); Append()
2) Open();
3) Open(); Edit()
Здесь задача заключается в том, чтобы реализовать однородные действия с минимальными различиями — то есть редактировать данные, используя как можно меньше конкретных разнородных конструкций типа заведения еще Query для выполнения им действий... для этого как раз и служит TUpdateSQL
А задача Query — в том, чтобы дать возможность редактирования и просмотра данных.
И, кстати, если даже делать "SELECT * FROM clients" — этот файл DELxx.MB все равно создается. Так что возвращаются, или нет данные, не имеет значения.
Почему я не использую INSERT — да потому, что при этом придется конструировать SQL — выражение вручную, а при множестве полей различных типов в таблице это становится несколько утомительно. Представим, что набор полей периодически изменяется. Тогда поддержка программы превращается в муку. А для TQuery — достаточно просто перестроить TUpdateSQL и добавить контрол.
Отредактировано iAlexander — 26/11/2004, 17:16 |
|
AVC |
Отправлено: 26.11.2004, 15:46 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
А я размещаю на форме два компонента класса Query и спокойно решаю все вопросы единства интерфейса. Один Query для Select'a другой для разных мелких проблем, в том числе и для выполнения команд SQL не возвращающих наборов данных.
Отредактировано AVC — 26/11/2004, 15:59 |
|
iAlexander |
Отправлено: 26.11.2004, 15:58 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
AVC
А каким образом Вы реализуете добавление?
То есть где пользователь может заполнять поля, и как потом введенные значения используются? |
|
AVC |
Отправлено: 26.11.2004, 16:02 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
По обстановке. Иногда прямо в гриде — тогда работает основной Query иногда через дополнительную опросную форму тогда рботает дополнительный Query.
SELECT * FROM clients WHERE Num = -1 как мне кажется возвращает пустой набор, или я не прав? |
|
iAlexander |
Отправлено: 26.11.2004, 16:05 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
Да, Вы правы.
Смотрите мое исправление (2-е сообщение) .
А дополнительная опросная форма — она содержит TDBEdit или TEdit?
Если DB, то на какой TDataSet они завязаны? |
|
AVC |
Отправлено: 26.11.2004, 16:34 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE | А дополнительная опросная форма — она содержит TDBEdit или TEdit?
|
Обратно-же когда как, но чаще TEdit.
QUOTE | Если DB, то на какой TDataSet они завязаны |
На основной.
Если ваша форма предназначена для работы по одной записи то можно работать и так как вы предлагаете в 1м посте. В моих терминах это и есть вспомогательная опросная форма. |
|
iAlexander |
Отправлено: 26.11.2004, 16:42 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
Мы друг друга поняли
У меня это как раз и есть опросная форма. Она вызывается при редактировании/добавлении/просмотре, с найденным id для просмотра/редактирования.
Однако вопрос-то остается: DELxx.MB. Кстати, посмотрите на свою реализацию — возможно во время редактирования записей на опросной форме с TDB у Вас то же самое происходит. |
|
AVC |
Отправлено: 26.11.2004, 17:10 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE | возможно во время редактирования записей на опросной форме с TDB у Вас то же самое происходит |
Нет. Я работаю не с Paradox.
Для создания пустой записи я пользуюсь непосредственно основным Query
т.е. командой Insert. Получаю пустышку, заполняю начальными значениями и передаю DataSet в опросную форму (эта вместо той части которая справедливо возмутила Gedeon). По возврату автоматически, по информации о полях из DataSet, строю SQL Insert и выполняю его через вспомогательный запрос. Сопровождение UpdateSql считаю слишком муторным. Автоматический Insert сам сделает все что надо (примерно как это делает DataSet)
|
|
iAlexander |
Отправлено: 26.11.2004, 17:53 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
Можно поподробнее?
Я несколько запутался
Что есть пустышка, как она получается и после чего редактируется начальными значениями? Что передается и по чему автоматически строится Insert? Как он строится?
Если не лень, пожалуйста, отредактируйте Ваш ответ, при этом соблюдая последовательность вызовов и поименовав TDataSet'ы для ясности. |
|
AVC |
Отправлено: 26.11.2004, 18:21 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Просматриваем QryMain и считаем что пора добавить запись.
QryMain->Insert() порождает пустую строку в памяти и DataSet спозиционирован на ней.
Вызов формы редактирования, один из параметров QryMain.
Заполнение полей формой.
В зависимости от сложности запроса либо просто Post и Refresh.
Либо построение текста запроса Insert типа AnsiString sqltext = "Insert Into aaa.bbb (ff1, ff2, ...) Values (vv1, vv2 ...)";
QryWork->SQL->Text = sqltext; QryWork->Execute(); QryMain Refresh
После Refresh — QryMain позиционирую на новую запись.
Если нужно просто редактировать то QryMain->Insert() заменяется на QryMain->Edit() а дальше см. выше.
Дальше (если нужно) в понедельник. |
|
AVC |
Отправлено: 26.11.2004, 18:38 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Кстати. Мы несколько уклонились от основного вопроса топика.
"В чем причина возникновения этого файла" — рабочий файл для BDE SQL. В конце концов это просто имитатор нормального сервера бд.
"можно ли ее устранить?" — я не знаю, но предлагаю обойти эту проблему. Почему бы при старте приложения не вызвать чистильщика — удалить файлы del??.mb ?
|
|
iAlexander |
Отправлено: 26.11.2004, 19:07 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
1)ОК, спасибо. ответ на основной вопрос я получил. Насчет чистильщика — хорошая идея!
2)А такой путь, который описан Вами, кажется мне не менее трудоемким, чем мой.
Основное же отличие — в том, что у меня нет QryMain (кстати, что это, Table, Query, или без разницы). И я могу добавлять новое поле с ходу, не вызывая перед этим список имеющихся (и это для меня необходимо). (еще раз скажу, что открывать Query мне приходится лишь постольку, поскольку закрытый он не может сделать Append(), и всего лишь)
3) Формат Insert я знаю . Способ его выполнения тоже.
Вопрос был — автоматически ли Вы генерируете эту строку (допустим, обходом всех полей датасета). Я, например, таким образом делаю, когда генерирую строку поиска (это, кстати, еще одна форма использования моего Query — наряду с добавлением/редактированием/просмотром). |
|
AVC |
Отправлено: 27.11.2004, 14:59 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE | А такой путь, который описан Вами, кажется мне не менее трудоемким, чем мой.
Основное же отличие — в том, что у меня нет QryMain (кстати, что это, Table, Query, или без разницы).
|
Хозяин барин
QryMain это без разницы (TDataSet), хотя в силу специфики СУБД с TTable не работаю.
QUOTE | Вопрос был — автоматически ли Вы генерируете эту строку (допустим, обходом всех полей датасета).
|
Да автоматически. Не пивел в примере код, думал это и так очевидно в свете нашего диалога.
Наша разница состоит в том, что когда пользователь принимает решение о необходмисти добавления строки у меня уже есть открытый DataSet (именно просмотрев его он и пришел к такой необходимости)("просмотр с редактированием"). Для вашего случая, как мне кажется, более характерна следующая схема — заполнение опросной формы, сохранение результата ("циклический ввод").
Мой опыт подсказывает, что в случае циклического воода (конечно если речь идет не о простом редакторе таблиц) создание универсальной опросной формы на таком уровне не оправдано. Вывод — делать для каждого класса вводимой в цикле информации свою форму и после опроса выполнять SQL'евский Insert.
(Но обратно же — все по желанию разработчика).
Если вы помните, то наш диалог начался с того, что нет ничего страшного в двух DataSet'ах на форме. |
|
AVC |
Отправлено: 27.11.2004, 15:10 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Уф. Все стало на свое место. Простите, что не сразу понял
Как то сразу зацепился за фразу "... используя как можно меньше конкретных разнородных конструкций типа заведения еще Query для выполнения им действий ..."
Ваш метод совершенно оправдан, если вы делаете универсальную, самонастраивающуюся форму для добавления, изменения, поиска (удаления?) строк, из любой, заранее не известной, таблицы. Тот самый редактор таблицы.
(с моей точки зрения вещь, более менее удобная для админа, но мало пригодная для пользователя).
Отредактировано AVC — 27/11/2004, 15:18 |
|
iAlexander |
Отправлено: 29.11.2004, 13:18 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
AVC
если вы делаете универсальную, самонастраивающуюся форму для добавления, изменения, поиска (удаления?) строк, из любой, заранее не известной, таблицы
Да, это хорошая идея, но, как Вы правильно заметили, малопригодная для конечного пользователя. Я так не делаю — у меня отдельные формы под разные таблицы. Однако, поскольку их (форм и таблиц) много, очень хорошо, когда для реализации требуется минимум компонентов — тогда единообразие все же сохраняется, и потом легче это сопроводить и изменить все синхронно.
Циклический ввод я использовал раньше, потом отказался по просьбам пользователей.
Сейчас, после нашего диалога, я уже могу сформулировать мысль в том виде, в котором она и была задумана, а впоследствии реализована.
Моя цель — редактирование данных в TDBEdit-подобных контролах — с тем, чтобы каждый контрол был сразу связан с полем таблицы, которому он соответствует (в этом также случае отпадает необходимость обхода полей датасета с целью создания оператора INSERT/UPDATE). При этом отсутствуют какие-либо предварительные манипуляции с датасетами — и поэтому Query под этими контролами сам предоставляет возможность редактирования данных в контролах (посредством Append, из-за которого необходимо делать Open)
Единственный, на мой взгляд, недостаток такого решения — это присутствие и необходимость своевременного обновления TUpdateSQL. Выходом для себя я вижу создание собственного компонента, реализующего вся эту функциональность в себе одном. И для начинки здесь уже можно использовать либо компот TQuery с TUpdateSQL, либо способ, предложенный Вами (с еще одним Query). Вообще разницы здесь никакой — и там, и тут нужно будет конструировать SQL выражения. Но коль уж TUpdateSQL имеет три поля под это дело — можно и воспользоваться. ;-)
(добавлено: да, обход полей — не контролов. сорри)
Отредактировано iAlexander — 29/11/2004, 16:28 |
|
AVC |
Отправлено: 29.11.2004, 15:20 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE | в этом также случае отпадает необходимость обхода контролов с целью создания оператора INSERT/UPDATE |
Вообще-то я имел ввиду обход полей датасета.
Действительно я предпочитаю иметь второй Query вместо UpdateSql, при динамической генерации команд sql достаточно иметь один QryWork на приложение (такой у меня то же есть).
Могу отдать еще одну идею (реализована у меня в последнем проекте). В специальной таблице хранится описание фомы — какие и как элементы опрашивать и что потом с эти делать. Приложение зачитывает это описание, настраивает свои контролы и предлагает пользователю заполнить поля ввода. По нажатию "сохранить" проверяется что там пользователь понавводил и, если все правильно, выполняются действия. При изменении структур таблиц или добавлении новых требований достаточно просто поменять тест описания а не лезть в исходники. Плюс все нововведения доступны сразу всем без ожидания обновления.
|
|
iAlexander |
Отправлено: 29.11.2004, 15:36 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 70
|
Я тоже приходил к этой идее. Несколько с другой целью, правда — мне нужно было настроить для каждого контрола уровень доступа для каждого типа пользователя. (Виден/Доступен/Редактируем).
Это действительно очень удобно:
1) экономия ресурсов при отсутствии DB контролов не хилая
2) обращение к БД можно организовывать вообще через один компонент.
Только у меня мало времени для реализации таких удачных идей.
Обычно все приходится по-дедовски делать |
|
AVC |
Отправлено: 29.11.2004, 16:08 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Удачи |
|