Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
1-90582
-=GaLaN=-
2002-02-08 13:10
2002.02.28
SpinEdit - как обрабатывать изменения?


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


14-90649
panov
2002-01-14 07:17
2002.02.28
Нужен алгоритм


1-90558
Ирина
2002-02-11 18:20
2002.02.28
DLLка грохается на Free формы


3-90466
vlv
2002-02-01 19:10
2002.02.28
Сообщение об ошибке СУБД





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский