| 
| 
 | Вопрос # 6 137/ вопрос закрыт / | 
 |  Приветствую, уважаемые эксперты!
 Помогите разобраться... Требовалось написать программу справочник, всё работало, после, что то добавил и перестала запускаться, выдает ошибку "ADOTable1: Cannot perform this operation on a closed dataset" на строке "DMForm.ADOTable1.First".
 
 P.S. DMForm это DataModule
 Приложение:Переключить в обычный режим procedure TMainForm.FormActivate(Sender: TObject);var  nd, nr: TTreeNode;  fds: string;begin  MainForm.TreeView1.Items.BeginUpdate;  MainForm.TreeView1.SortType := stNone;  MainForm.TreeView1.Items.Clear;  //DMForm.ADOTable1.Open;  DMForm.ADOTable1.First;  i := 0;   if DMForm.ADOTable1.RecordCount > 0 then begin    while not DMForm.ADOTable1.Eof do begin      i := i + 1;      RObject[i].ItemU1 := DMForm.ADOTable1.Fields[0].AsInteger;      RObject[i].ItemU2 := 0;      nd := MainForm.TreeView1.Items.AddObject(nil, DMForm.ADOTable1.Fields[1].AsString, nil);      fds := DMForm.ADOTable1.Fields[0].AsString;      DMForm.ADOQuery1.Active := False;      DMForm.ADOQuery1.Parameters.ParamByName('razd').Value := fds;      DMForm.ADOQuery1.Active := True;       if DMForm.ADOQuery1.RecordCount > 0 then begin        DMForm.ADOQuery1.First;        while not DMForm.ADOQuery1.Eof do begin          i := i + 1;          RObject[i].ItemU1 := DMForm.ADOQuery1.Fields[2].AsInteger;          RObject[i].ItemU2 := DMForm.ADOQuery1.Fields[0].AsInteger;          nr := MainForm.TreeView1.Items.AddChildObject(nd, DMForm.ADOQuery1.Fields[1].AsString,
nil);          DMForm.ADOQuery1.Next;        end;      end;       DMForm.ADOTable1.Next;    end;  end;  //DMForm.ADOTable1.Close;  DMForm.ADOTable1.Filter := '';  DMForm.ADOQuery1.Filter := '';  MainForm.TreeView1.Items.EndUpdate;end;
|  |   Вопрос задал: serox (статус: Посетитель)Вопрос отправлен: 15 мая 2012, 21:09
 Состояние вопроса: закрыт, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 11; последнее сообщение — 16 мая 2012, 21:52; участников в обсуждении: 3. 
|   | ANBsoft (статус: Студент), 15 мая 2012, 21:19 [#1]:9 строка - отключена команда открытия таблицы. |  
|   | serox (статус: Посетитель), 15 мая 2012, 22:12 [#2]:Если с 9 и 38 снять комментарий, то дерево показывает, а выборка не происходит... 
 Хотя в другой аналогичной программе всё работает и без Открыть/Закрыть...
 That will be, you and do not learn, if never will try! ^__^ |  
|   | Мережников Андрей (статус: Абитуриент), 15 мая 2012, 22:49 [#3]: Цитата (serox): а выборка не происходит. ну так включи отладчик и посмотри пошагово где "затык". Может какое условие неправильно прописано. А делать выборку на закрытом наборе - это все равно, что пытаться пива выпить, не открыв бутылку
 |  
|   | Мережников Андрей (статус: Абитуриент), 15 мая 2012, 22:51 [#4]:и в догонку - нельзя было сделать всю выборку одним запросом? |  
|   | serox (статус: Посетитель), 15 мая 2012, 23:01 [#5]:Мережников Андрей: Повторяю ещё раз, есть 2 программы. Первая - отлично всё работает и без Открыть/Закрыть (так как она написана в вопросе, только другие названия переменных). Вторая - я её изменяю, и после переименования некоторых переменных, начала выскакивать ошибка...
 That will be, you and do not learn, if never will try! ^__^ |  
|   | Мережников Андрей (статус: Абитуриент), 15 мая 2012, 23:08 [#6]: Цитата (serox): Повторяю ещё раз, 
 Цитата (Мережников Андрей): включи отладчик и посмотри пошагово где "затык" а еще проверь значения свойств в компонентах
 |  
|   | serox (статус: Посетитель), 16 мая 2012, 00:16 [#7]:Свойства все одинаковые, отладчик с открыть/закрыть проходит так же как и в рабочей программе, но не делает выборку... Просто у меня такое уже не в первый раз происходит с ADO... That will be, you and do not learn, if never will try! ^__^ |  
|   | ANBsoft (статус: Студент), 16 мая 2012, 00:31 [#8]:Слишком все запутано, и куча лишних команд. Я никогда не работал через ADO-компоненты, так что если ошибаюсь, то пусть знатоки поправят.
 
   DMForm.ADOTable1.Open; //если таблица не открыта, то с ней нельзя работать, так что Open нужно выполнять
//  DMForm.ADOTable1.First; //можно убрать, после Open курсор и так на первой строке
  i := 0;
 
//  if DMForm.ADOTable1.RecordCount > 0 then begin //лишняя проверка, если RecordCount=0, то ADOTable1.Eof будет сразу
True
    while not DMForm.ADOTable1.Eof do begin
      i := i + 1;
      RObject[i].ItemU1 := DMForm.ADOTable1.Fields[0].AsInteger;
      RObject[i].ItemU2 := 0;
      nd := MainForm.TreeView1.Items.AddObject(nil, DMForm.ADOTable1.Fields[1].AsString, nil);
//      fds := DMForm.ADOTable1.Fields[0].AsString; //зачем вообще эта переменная?
//      DMForm.ADOQuery1.Active := False;  //по логике здесь он и так должен быть закрыт
      DMForm.ADOQuery1.Parameters.ParamByName('razd').Value := DMForm.ADOTable1.Fields[0].AsString; //Сразу без всяких
fds
      DMForm.ADOQuery1.Active := True;
 
//      if DMForm.ADOQuery1.RecordCount > 0 then begin //лишнее - выше описал
//        DMForm.ADOQuery1.First; //лишнее - выше описал
        while not DMForm.ADOQuery1.Eof do begin
          i := i + 1;
          RObject[i].ItemU1 := DMForm.ADOQuery1.Fields[2].AsInteger;
          RObject[i].ItemU2 := DMForm.ADOQuery1.Fields[0].AsInteger;
          nr := MainForm.TreeView1.Items.AddChildObject(nd, DMForm.ADOQuery1.Fields[1].AsString,
nil);
          DMForm.ADOQuery1.Next;
        end;
      DMForm.ADOQuery1.Active := False;  //закрывать после использования
//      end;
 
      DMForm.ADOTable1.Next;
    end;
//  end;
  DMForm.ADOTable1.Close;  //если больше не нужно, то закрытьВ логику работы не вникал, так как не все есть в листинге, но так с деревьями не работают.Ваш код загрузит только один уровень вложения.
 Приведу кусок кода из своего проекта. Не претендую на предельную оптимальность, но 1) компонент доступа используется только один, 2) запрос к базе выполняется всего один раз, 3) глубина вложения дерева не ограничена, 4) обратите внимание на свойство Data у TTreeNode, возможно RObject станет вообще не нужен.
 
 //Работа с деревьями
 
Procedure ClearTree(T:TTreeView);
Var n : Integer;
Begin
  T.Selected:=Nil;
  for n:=0 to T.Items.Count-1 do begin
    Dispose(T.Items[n].Data);
  end;
  T.Visible:=False;
  T.Items.Clear;
  T.Visible:=True;
End;
 
Procedure LoadSubTree(T:TTreeView;R:TTreeNode;Q:TIBQuery;FN:String;IDSelect:Integer);
Var I : PInteger;
    Last:Integer;
    TekNode:TTreeNode;
    b:TBookmark;
Begin
  Q.First;
  while Not Q.Eof do begin
    if Q.FieldByName('Parent').AsInteger=PInteger(R.Data)^ then begin
      Last:=Q.FieldByName('ID').AsInteger;
      b:=Q.GetBookmark;
      New(I);
      I^:=Last;
      TekNode:=T.Items.AddChildObject(R,Q.FieldByName(FN).AsString,I);
      if Last=IDSelect then T.Selected:=TekNode;
      LoadSubTree(T,TekNode,Q,FN,IDSelect);
      Q.GotoBookmark(b);
      Q.FreeBookmark(b);
    end;
    Q.Next;
  end;
End;
 
Procedure LoadTree(T:TTreeView;Q:TIBQuery;FN:String;IDSelect:Integer);
Var I : PInteger;
    Last:Integer;
    TekNode:TTreeNode;
    b:TBookmark;
begin
  ClearTree(T);
  Q.FetchAll;
  if Q.RecordCount=0 then Exit;
  T.Visible:=False;
  Q.First;
  while Not Q.Eof do begin
    if Q.FieldByName('Parent').AsInteger=0 then begin
      Last:=Q.FieldByName('ID').AsInteger;
      b:=Q.GetBookmark;
      New(I);
      I^:=Last;
      TekNode:=T.Items.AddObject(Nil,Q.FieldByName(FN).AsString,I);
      if Last=IDSelect then T.Selected:=TekNode;
      LoadSubTree(T,TekNode,Q,FN,IDSelect);
      Q.GotoBookmark(b);
      Q.FreeBookmark(b);
    end;
    Q.Next;
  end;
  T.Visible:=True;
End;Компоненты доступа из закладки InterBase - но идея должна быть понятна. |  
|   | Мережников Андрей (статус: Абитуриент), 16 мая 2012, 18:07 [#9]: Цитата (ANBsoft): // if DMForm.ADOTable1.RecordCount > 0 then begin //лишняя проверка, если RecordCount=0, то ADOTable1.Eof будет сразу True не совсем так - если верить документации, то одно только значение ADOTable1.Eof, установленное в true, еще не значит, что таблица пуста. При пустой таблице в true должны быть установлены сразу 2 свойства: ADOTable1.Eof и ADOTable1.Bof
 |  
|   | ANBsoft (статус: Студент), 16 мая 2012, 21:42 [#10]:Я же писал, что не работал с ADO компонентами, а у Interbase компонентов (у TTable и TQuery вроде тоже), если сразу после открытия датасета EoF=True, значит выборка пуста. Оно и логично, BoF=True значит что была выбрана последняя запись в выборке, если записи не вычитывались, значит их просто нет. |  
|   | Мережников Андрей (статус: Абитуриент), 16 мая 2012, 21:52 [#11]:да это не только для ADO написано. Такая вот странность дельфи. меня после foxpro это тоже сильно удивило. |  27 мая 2013, 12:09: Вопрос закрыт (решение принял DNK): Автор потерял интерес к вопросу Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |