Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.02.28;
Скачать: CL | DM;

Вниз

Глюки 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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.008 c
4-90717
Delphimun
2001-12-20 12:55
2002.02.28
Как #0 сообщение от клавы о нажатии клавиши?


1-90615
Alex Nazarenko
2002-02-12 07:33
2002.02.28
Отчеты для матричного принтера


14-90633
Mz
2002-01-08 10:53
2002.02.28
подмена заголовка IP пакета


1-90619
vitnt2000
2002-02-13 09:34
2002.02.28
Подпись ActiveX


14-90662
Polevi
2002-01-15 17:46
2002.02.28
Civilization 3