Форум: "Базы";
Текущий архив: 2002.02.28;
Скачать: [xml.tar.bz2];
ВнизГлюки ADO часть 2-ая Найти похожие ветки
← →
RAVEN (2002-01-28 15:45) [0]Доброё время суток, Мастера! Проблема в следующем: Мне нужно удалить некоторые записи из одной таблицы. Всё бы ничего, но эти записи подчинены иерархии, т.е. одна является дочерней другой и т.д... Если какие-нибудь предложения будут по поводу удаления, готов их выслушать(заранее спасибо). Но проблема в том, что мой способ удаления что-то не совсем корректно работает. Значит способ такой. Я вешаю на обработчик события BeforeDelete набора данных(DS:TADODataSet, например), такую строку
PostMessage(MainForm.Handle,DSM_DELETEDOCUMENT,Integer(DataSet),DataSet.Fields[0].AsInteger);
Ниже приведён обработчик мессаджа DSM_DELETEDOCUMENT
procedure TMainForm.DeleteDocument(var Message:TMessage);
var DS:TADODataSet;
Value:integer;
begin
Value:=Message.LParam;
DS:=TADODataSet(Message.WParam);
if not (DS.State=dsInactive) then
While DS.Locate("Parent",Value,[]) do DS.Delete;
end;
При трассировке события BeforeDelete и AfterDelete срабатывают, но дочерние записи удаляются или не все или не удаляются вообще, а главная материнская запись удаляется всегда. Помогите пожалуйста понять что происходит?
← →
SergSuper (2002-01-28 16:36) [1]Я конечно понимаю, что это всё глюки АДО, но зачем такой огород с PostMessage городить?
Кстати непонятно на чем база - на MSSQL или Access?
Если на первом, то это надо делать на стороне сервера.
← →
RAVEN (2002-01-28 16:41) [2]Прошу прощения, база на Access. А насчёт "огорода" я бы с удовольствием выслушал ваш способ.
← →
Delirium (2002-01-28 16:48) [3]А в чём проблема - поместил все свои действия в BeforeDelete, или есть какая-то загвоздка?
← →
RAVEN (2002-01-28 16:53) [4]Загвоздка в том что таблица одна, а в ней реализовано дерево.
← →
Delirium (2002-01-28 17:02) [5]Ну и что? Вводишь пременную, которая будет "включать" или "выключать" обработку в зависимости от того удаляется родитель или потомки. Но я бы, на самом деле, сделал удаление через SQL - оно и быстрее и надёжнее.
← →
RAVEN (2002-01-29 08:38) [6]Я наверное чего-то не понимаю, но потомки в дереве тоже могут рассматриваться как родители. Самый лучший способ удалить узлы дерева это рекурсивная процедура, но с событием это не прокатит, можно также сформировать список ключей удаляемых родительских(относительно дочерних узлов)хотя это самый извращённый способ. Может я просто заработался. Если не трудно, приведите пожалуйста пример вышесказанных Вами слов.
← →
Alex Y (2002-01-29 10:03) [7]Попробуй такой вариант:
Deleting := False - признак процесса удаления
provedure tMyTable.BeforeDelete(...)
begin
if Deleting then Exit;
Deleting := True;
DeleteChilds(FieldByName("Parent").AsString); // Ушел в
рекурсию
Deleting := False;
end;
← →
Delirium (2002-01-29 11:59) [8]А я бы сделал так:
procedure TForm1.ADOTable1BeforeDelete(DataSet: TDataSet);
begin
ADOTable1.Connection.Execute("delete MyTable where idField in (...)");
end;
procedure TForm1.ADOTable1AfterDelete(DataSet: TDataSet);
begin
ADOTable1.Requery;
end;
а что будет на месте "..." - это уже из условий задачи.
← →
Fay (2002-01-29 12:04) [9]Опиши таблу
← →
RAVEN (2002-01-29 16:33) [10]>AlexY Дело в том что DeleteChilds будет вызывать метод Delete у той же таблицы. Т.е. будет возникать бесконечная рекурсия.
← →
RAVEN (2002-01-29 16:38) [11]>FAY Ну суть таблы такая:
ID Parent Field1, Field2,...
Поле ID и Parent одного типа, т.е. целочисленные, в Parent заносится ID родительского док-та, если стоит 0, то родителя нет. Всё.
← →
RAVEN (2002-01-29 16:47) [12]>Delirium
procedure TForm1.ADOTable1BeforeDelete(DataSet: TDataSet);
begin
ADOTable1.Connection.Execute("delete MyTable where idField in (...)");
end;
Дело в том, что для подзапроса мне нужно будет знать все ID родительских полей, чтобы удалить их за одну команду.
← →
Delirium (2002-01-29 16:57) [13]Тебе нужна рекурсивная процедура удаления в MSSQL
← →
RAVEN (2002-01-29 17:10) [14]>Delirium Господа, БД на акцессе (файл-серверная), а клиент на Делфях.
← →
Delirium (2002-01-29 17:33) [15]Тогда делай как Alex Y сказал
← →
Alex Y (2002-01-30 05:47) [16]2 RAVEN для этого тебе и нужен флаг Deleting.
Событие да, будет вызываться, однако флаг тебя просто выводит из него. А по окончании удаления меняешь флаг и событие опять становится работоспособным.
← →
handra (2002-01-30 11:07) [17]Хэх, а кто-нить разницу между SendMessage и PostMessage помнит?
Так вот, SendMessage возвращает управление после отработки сообщения, а PostMessage возвращает управление сразу (помещает сообщение в очередь). И наверняка, отсутствую внешний ключ (foreign key) Table.Parent->Table.ID
И, если используется MSSQL2000, почему не сделать каскадное удаление? Или оформить все в виде хранимой процедуры.
P.S. я такие задачи всегда решал с помощью рекурсивной хранимой процедуры...
← →
handra (2002-01-30 11:34) [18]Еще, у меня Access2002 (входит в Office XP) - чумовая вещь, поддерживает каскадные удаление и обновление...
← →
Delirium (2002-01-30 12:05) [19]>handra
Дело тут не в разнице между Send и Post, и не в каскадном удалении - таблица одна, и не в рекурсивной процедуре - работаем с ACCESS. Хотя с последним, стоит подумать, я никогда не создавал поцедуры в ACCESS, но попробывать можно.
← →
Fay (2002-01-30 17:55) [20]Пардон! Не понял сразу , что речь об ACCSESS-е
← →
kig (2002-01-30 18:44) [21]А связь таблицы один-к-многим саму на себя (ID - IDParent) + каскадное удаление не подходит? (Правда в этом случае признаком root значение IDParent = значение ID).
← →
Delirium (2002-01-30 18:48) [22]Нет, так как возникает проблема с блокировкой, по крайней мере в ACCESS2000
← →
kig (2002-01-30 18:50) [23]Если таблицу открыть - то блокировка наблюдается - если толкать команду из sql - то все удаляет нормально.
← →
Delirium (2002-01-30 18:56) [24]А действительно! Эй RAVEN, решение твоей проблемы элементарно!
kig, а ты молоток!
← →
RAVEN (2002-02-04 12:58) [25]Ребята, всем спасибо огромное, но я сделал всё-таки по своему с PostMessage просто у меня на процедуре обработки AfterDelete стояла процедура которая "тормозила" обработку сообщений. Я её тоже на мессаг "посадил" и всё заработало. Ещё раз всем спасибо.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.02.28;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.004 c