C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
ClientDataSet, как?
Inga
Отправлено: 27.12.2005, 14:46


Ученик-кочегар

Группа: Участник
Сообщений: 12



Есть код заполняющий ClientDataSet:
CODE

TFieldDefs *pDefs = Form1->ClientDataSet4->FieldDefs;

          TFieldDef *pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 25;
          pDef->Name = "ID";

          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "Collector";

          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "REC";


          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "Complex";


          TIndexDef *pIDef = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef->Fields = "Collector";
          pIDef->Name = "MyIndex";

          TIndexDef *pIDef2 = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef2->Fields = "REC";
          pIDef2->Name = "MyIndex2";


          TIndexDef *pIDef3 = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef3->Fields = "Complex";
          pIDef3->Name = "MyIndex4";

          Form1->ClientDataSet4->CreateDataSet();

//далее заполнение данными
****************

//затем отображение в гриде через DataSource:
Form1->DataSource5->DataSet = Form1->ClientDataSet4;



Как теперь очисть ClientDataSet4 от индексов и полей, т.е. привести его в состояние, как будто его только положили на форму? Это нужно для формирования новой структуры ClientDataSet4. Динамически создавать ClientDataSet4 мне не подходит. Формируется в одной форме, используется в другой.

Пробовала чистить так:
CODE

if(Form1->ClientDataSet4->FieldDefs->Count)
       {
 
          Form1->ClientDataSet4->Edit();
          Form1->ClientDataSet4->FieldDefs->Clear();
          Form1->ClientDataSet4->Fields->Clear();
          Form1->ClientDataSet4->FieldDefs->Update();
          Form1->ClientDataSet4->IndexDefs->Clear();
          Form1->ClientDataSet4->IndexDefs->Update();
          Form1->ClientDataSet4->Close();
       }

//или так
if(Form1->ClientDataSet4->FieldDefs->Count)
{
Form1->DataSource5->DataSet->Close();
}

//или так
if(Form1->ClientDataSet4->FieldDefs->Count)
{
Form1->DataSource5->DataSet->Close();
}


Если написать так:
CODE

if(Form1->ClientDataSet4->FieldDefs->Count)
       {
          Form1->ClientDataSet4->Edit();
          Form1->ClientDataSet4->IndexDefs->Clear();
          Form1->ClientDataSet4->IndexDefs->Update();
          Form1->ClientDataSet4->FieldDefs->Clear();
          Form1->ClientDataSet4->FieldDefs->Update();
          Form1->ClientDataSet4->Close();
       }


Исключение пишет поле ID уже существует.

Если добавить Form1->ClientDataSet4->Fields->Clear(); пишет Field not found
Как привести ClientDataSet4 в состояние полной очистки?
olegenty
Отправлено: 27.12.2005, 15:02


Ветеран

Группа: Модератор
Сообщений: 2412



а вообще, надо ли это? если всё такое динамическое, то можно и экземпляр TClientDataSet удалять и создавать по мере необходимости...
Inga
Отправлено: 27.12.2005, 15:14


Ученик-кочегар

Группа: Участник
Сообщений: 12



У меня формируется ClientDataset в одной форме, затем все, что он содержит отображается в другой форме. Придется много кода переделывать если создавать ClientDataset динамически.
Если понять, как очисть структуру ClientDataset, то ничего переделывать не надо.
Inga
Отправлено: 27.12.2005, 15:23


Ученик-кочегар

Группа: Участник
Сообщений: 12



Может надо добавить удаление объектов pDef и pIDef?

Объекты pDef и pIDef не глобальные, создаются в обработчике. Я предполагала, что они наполняют ClientDataSet4 и потом сами перестают существовать.
Как их удалять? Делать проверку
if(pDef)
pDef = NULL ?

olegenty
Отправлено: 27.12.2005, 15:23


Ветеран

Группа: Модератор
Сообщений: 2412



тогда наверное не стоит оперировать и FieldDefs и Fields. точно помню, что пользовался только Fields, и всё работало корректно. и не надо переводить ClientDataset в режим редактирования перед удалением полей и индексов. вместо этого его надо закрыть.
Inga
Отправлено: 27.12.2005, 15:47


Ученик-кочегар

Группа: Участник
Сообщений: 12



>тогда наверное не стоит оперировать и FieldDefs

Подскажите, пожалуйста, как все тогда создовать в ClientDataset?
olegenty
Отправлено: 27.12.2005, 16:24


Ветеран

Группа: Модератор
Сообщений: 2412



с перманентными полями
но и так должно работать:
CODE

Form1->ClientDataSet4->Close();
Form1->ClientDataSet4->FieldDefs->Clear();
Form1->ClientDataSet4->FieldDefs->Update();
Form1->ClientDataSet4->IndexDefs->Clear();
Form1->ClientDataSet4->IndexDefs->Update();

после этого Form1->ClientDataSet4 чист.
Inga
Отправлено: 27.12.2005, 16:57


Ученик-кочегар

Группа: Участник
Сообщений: 12



>но и так должно работать:

Не работает. sad.gif
Привожу полный код, может так легче будет понять:
CODE

//в начале обработчика
if(Form1->ClientDataSet4->FieldDefs->Count)
      {
Form1->ClientDataSet4->Close();
Form1->ClientDataSet4->FieldDefs->Clear();
Form1->ClientDataSet4->FieldDefs->Update();
Form1->ClientDataSet4->IndexDefs->Clear();
Form1->ClientDataSet4->IndexDefs->Update();
      }

//далее в этом же обработчике:

If(первое условие формирования ClientDataSet4)
{
TFieldDefs *pDefs = Form1->ClientDataSet4->FieldDefs;

          TFieldDef *pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 25;
          pDef->Name = "ID";

          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "Collector";

          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "REC";


          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "Complex";



          TIndexDef *pIDef = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef->Fields = "Collector";
          pIDef->Name = "MyIndex";

          TIndexDef *pIDef2 = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef2->Fields = "REC";
          pIDef2->Name = "MyIndex2";


          TIndexDef *pIDef3 = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef3->Fields = "Complex";
          pIDef3->Name = "MyIndex4";  
          Form1->ClientDataSet4->CreateDataSet();


        // в цикле заполнение строк данными далее:


          Form1->ClientDataSet4->IndexName = "MyIndex";
          Form1->ClientDataSet4->First();
          Form1->DataSource5->DataSet = Form1->ClientDataSet4;

        ST->ShowModal();
}

If(второе условие формирования ClientDataSet4)
{
TFieldDefs *pDefs = Form1->ClientDataSet4->FieldDefs;
          TFieldDef *pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 25;
          pDef->Name = "ID";

          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "Collector";


          pDef = pDefs->AddFieldDef();
          pDef->DataType = ftString;
          pDef->Size = 40;
          pDef->Name = "REC";

          TIndexDef *pIDef = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef->Fields = "Collector";
          pIDef->Name = "MyIndex";

          TIndexDef *pIDef2 = Form1->ClientDataSet4->IndexDefs->AddIndexDef();
          pIDef2->Fields = "REC";
          pIDef2->Name = "MyIndex2";

          Form1->ClientDataSet4->CreateDataSet();

//далее код опущен
}


Приложение выполняется: cоздала условия, что бы выполнился первый if по формированию ClientDataSet4, затем создаю условия, чтобы попасть во второй if обработчика.
Получаю рисунок при вхождении во второй if на строке pDef->Name = "ID"; , причем точки останова показали, что код по очистке перед входом во второй if выполнился.

Присоединить изображение

Присоединить изображение

Inga
Отправлено: 27.12.2005, 17:06


Ученик-кочегар

Группа: Участник
Сообщений: 12



Добавила в код очистки строку Form1->ClientDataSet4-Fields->Clear();
не помогло, та же ошибка.
Inga
Отправлено: 27.12.2005, 19:57


Ученик-кочегар

Группа: Участник
Сообщений: 12



Наиболее правильный код получился такой:
CODE

      if(Form1->ClientDataSet4->FieldDefs->Count)
       {
        Form1->ClientDataSet4->Edit();
        Form1->ClientDataSet4->IndexDefs->Clear();
        Form1->ClientDataSet4->FieldDefs->Clear();
        Form1->ClientDataSet4->FieldDefs->Count;
        Form1->ClientDataSet4->Close();
       }

Этот код делает равным нулю Form1->ClientDataSet4->FieldDefs->Count; Другие варианты не обнуляют FieldDefs.
Теперь проблема осталась такая:
Я в коде выше создаю три индекса, затем использую, например индекс под именем MyIndex4.
После очистки я создаю в ClientDataSet4 два индекса и получаю исключение (см.рисунок). Что ему не нравиться? Ведь я заново создаю индексы, поэтому MyIndex4 и не должно быть. Почему исключение?


Присоединить изображение

Присоединить изображение

olegenty
Отправлено: 28.12.2005, 07:46


Ветеран

Группа: Модератор
Сообщений: 2412



возможно, какоее-то из свойств на него указывает.
Inga
Отправлено: 29.12.2005, 11:47


Ученик-кочегар

Группа: Участник
Сообщений: 12



Научите, как правильно сделать с помощью динамического распределения памяти?
Написала в классе формы в разделе public: TClientDataSet * ClientDataSet4;

Перед использование пишу: Form1->ClientDataSet4 = new TClientDataSet(Form1);
Затем открываю другую форму и использую в ней ClientDataSet4 (сортировка по индексу). После закрытия формы пишу delete Form1->ClientDataSet4;
При попытке снова создать новый ClientDataSet4; опять пишет, что прошлый индекс MyIndex4 не найден.
Использование индекса в другой форме выглядит так:
CODE

Form1->ClientDataSet4->IndexName = "MyIndex4";
TFilterOptions FO;
FO << foCaseInsensitive;
Form1->ClientDataSet4->FilterOptions=FO;

AnsiString IDE = DBGrid1->Columns->Items[2]->FieldName;

Form1->ClientDataSet4->Filter = IDE +"=" +"'" + AnsiString(sEdit3->Text)+AnsiString("*") +"'";
if(sEdit3->Text=="")
  {
   Form1->ClientDataSet4->Filtered = false;
  }
  else
  {
   Form1->ClientDataSet4->Filtered = true;
  }
 

Если индекс не использовать, то есть не сортировать данные, то никаких ошибок при повторном заполнении ClientDataSet4 не возникает. Подскажите куда смотреть? sad.gif
olegenty
Отправлено: 29.12.2005, 11:59


Ветеран

Группа: Модератор
Сообщений: 2412



а если не создавать индекса, а вместо этого воспользоваться св-вом IndexFieldNames?
Inga
Отправлено: 29.12.2005, 12:50


Ученик-кочегар

Группа: Участник
Сообщений: 12



Все, спасибо, разобралась! smile.gif

Вернуться в Работа с базами данных в C++Builder