![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Глюки ADO часть 2-ая [D3, D4, D5, D6, MSSQL, Access]
RAVEN © (2002-01-28 15:45:00)Доброё время суток, Мастера! Проблема в следующем: Мне нужно удалить некоторые записи из одной таблицы. Всё бы ничего, но эти записи подчинены иерархии, т.е. одна является дочерней другой и т.д... Если какие-нибудь предложения будут по поводу удаления, готов их выслушать(заранее спасибо). Но проблема в том, что мой способ удаления что-то не совсем корректно работает. Значит способ такой. Я вешаю на обработчик события 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 срабатывают, но дочерние записи удаляются или не все или не удаляются вообще, а главная материнская запись удаляется всегда. Помогите пожалуйста понять что происходит?
RAVEN (2002-02-04 12:58:00) [1]Ребята, всем спасибо огромное, но я сделал всё-таки по своему с PostMessage просто у меня на процедуре обработки AfterDelete стояла процедура которая "тормозила" обработку сообщений. Я её тоже на мессаг "посадил" и всё заработало. Ещё раз всем спасибо.
Delirium (2002-01-30 18:56:00) [2]А действительно! Эй RAVEN, решение твоей проблемы элементарно!
kig, а ты молоток!
kig (2002-01-30 18:50:00) [3]Если таблицу открыть - то блокировка наблюдается - если толкать команду из sql - то все удаляет нормально.
Delirium (2002-01-30 18:48:00) [4]Нет, так как возникает проблема с блокировкой, по крайней мере в ACCESS2000
kig (2002-01-30 18:44:00) [5]А связь таблицы один-к-многим саму на себя (ID - IDParent) + каскадное удаление не подходит? (Правда в этом случае признаком root значение IDParent = значение ID).
Fay (2002-01-30 17:55:00) [6]Пардон! Не понял сразу , что речь об ACCSESS-е
Delirium (2002-01-30 12:05:00) [7]>handra
Дело тут не в разнице между Send и Post, и не в каскадном удалении - таблица одна, и не в рекурсивной процедуре - работаем с ACCESS. Хотя с последним, стоит подумать, я никогда не создавал поцедуры в ACCESS, но попробывать можно.
handra (2002-01-30 11:34:00) [8]Еще, у меня Access2002 (входит в Office XP) - чумовая вещь, поддерживает каскадные удаление и обновление...
handra (2002-01-30 11:07:00) [9]Хэх, а кто-нить разницу между SendMessage и PostMessage помнит?
Так вот, SendMessage возвращает управление после отработки сообщения, а PostMessage возвращает управление сразу (помещает сообщение в очередь). И наверняка, отсутствую внешний ключ (foreign key) Table.Parent->Table.ID
И, если используется MSSQL2000, почему не сделать каскадное удаление? Или оформить все в виде хранимой процедуры.
P.S. я такие задачи всегда решал с помощью рекурсивной хранимой процедуры...
Alex Y (2002-01-30 05:47:00) [10]2 RAVEN для этого тебе и нужен флаг Deleting.
Событие да, будет вызываться, однако флаг тебя просто выводит из него. А по окончании удаления меняешь флаг и событие опять становится работоспособным.
Delirium (2002-01-29 17:33:00) [11]Тогда делай как Alex Y сказал
RAVEN (2002-01-29 17:10:00) [12]>DeliriumГоспода, БД на акцессе (файл-серверная), а клиент на Делфях.
Delirium (2002-01-29 16:57:00) [13]Тебе нужна рекурсивная процедура удаления в MSSQL
RAVEN (2002-01-29 16:47:00) [14]>Delirium
procedure TForm1.ADOTable1BeforeDelete(DataSet: TDataSet);
begin
ADOTable1.Connection.Execute("delete MyTable where idField in (...)");
end;
Дело в том, что для подзапроса мне нужно будет знать все ID родительских полей, чтобы удалить их за одну команду.
RAVEN (2002-01-29 16:38:00) [15]>FAY Ну суть таблы такая:
ID Parent Field1, Field2,...
Поле ID и Parent одного типа, т.е. целочисленные, в Parent заносится ID родительского док-та, если стоит 0, то родителя нет. Всё.
RAVEN (2002-01-29 16:33:00) [16]>AlexY Дело в том что DeleteChilds будет вызывать метод Delete у той же таблицы. Т.е. будет возникать бесконечная рекурсия.
Fay (2002-01-29 12:04:00) [17]Опиши таблу
Delirium (2002-01-29 11:59:00) [18]А я бы сделал так:
procedure TForm1.ADOTable1BeforeDelete(DataSet: TDataSet);
begin
ADOTable1.Connection.Execute("delete MyTable where idField in (...)");
end;
procedure TForm1.ADOTable1AfterDelete(DataSet: TDataSet);
begin
ADOTable1.Requery;
end;
а что будет на месте "..." - это уже из условий задачи.
Alex Y (2002-01-29 10:03:00) [19]Попробуй такой вариант:
Deleting := False - признак процесса удаления
provedure tMyTable.BeforeDelete(...)
begin
if Deleting then Exit;
Deleting := True;
DeleteChilds(FieldByName("Parent").AsString); // Ушел в
рекурсию
Deleting := False;
end;
RAVEN (2002-01-29 08:38:00) [20]Я наверное чего-то не понимаю, но потомки в дереве тоже могут рассматриваться как родители. Самый лучший способ удалить узлы дерева это рекурсивная процедура, но с событием это не прокатит, можно также сформировать список ключей удаляемых родительских(относительно дочерних узлов)хотя это самый извращённый способ. Может я просто заработался. Если не трудно, приведите пожалуйста пример вышесказанных Вами слов.