Как я могу добавить поля в клиентский набор данных во время выполнения? - PullRequest
7 голосов
/ 08 февраля 2011

У меня есть TClientDataSet, который предоставляется набором данных TTable.Набор данных имеет два поля: почтовый индекс (строка, 5) и улица (строка, 20)

Во время выполнения я хочу отобразить третье поле (строка, 20).Процедура этого поля получает почтовый индекс в качестве параметра и возвращает город, принадлежащий этому почтовому индексу.

Проблема только в добавлении вычисляемого поля к уже существующим.Заполнение самих данных не является проблемой.

Я пытался:

  cds.SetProvider(Table1);
  cds.FieldDefs.Add('city', ftString, 20);

  cds.Open;

  cds.Edit;
  cds.FieldByName('city').AsString := 'Test';  // --> errormessage (field not found)
  cds.Post;

cds - это мой клиентский набор данных, Table1 - это таблица парадоксов, но проблема та же с другими базами данных.

Заранее спасибо

Ответы [ 5 ]

20 голосов
/ 08 февраля 2011

Если вы хотите добавить дополнительные поля, помимо тех, которые существуют в базовых данных, вам также необходимо добавить существующие поля вручную. Набор данных должен быть закрыт при добавлении полей, но вы можете иметь необходимые метаданные с FieldDefs.Update, если вы не хотите отслеживать все детали полей вручную. В основном как то так:

var
  i: Integer;
  Field: TField;
begin    
  cds.SetProvider(Table1);

  // add existing fields
  cds.FieldDefs.Update;
  for i := 0 to cds.FieldDefs.Count - 1 do 
    cds.FieldDefs[i].CreateField(cds);

  // add calculated field
  Field := TStringField.Create(cds);
  Field.FieldName := 'city';
  Field.Calculated := True;
  Field.DataSet := cds;

  cds.Open;
end;


См. Также отличную статью от Кэри Дженсен .

4 голосов
/ 09 февраля 2011

Ну, я нашел более простое решение, так как у меня есть 24 поля в моем sql, я не хотел добавлять их все вручную, поэтому вместо этого я добавил фиктивное поле в оператор sql:

select '      ' as city, the rest of the fields ... 

, которое яможно изменить в моей программе событие OnAfterOpen.

Ну, я должен был определить в sql, как долго это поле должно быть, оставляя достаточно пустых мест, например 5 пустых мест для 5 символов, поэтому я должен знать, как долго может быть название города.

2 голосов
/ 13 мая 2015

Вы должны использовать CreateDataset после добавления поля:

cds.SetProvider(Table1);
cds.FieldDefs.Add('city', ftString, 20);
cds.CreateDataset; 

cds.Open;
cds.Edit;
cds.FieldByName('city').AsString := 'Test';  
cds.Post;
2 голосов
/ 06 июня 2014

Хотел бы поделиться более точным Запросом для несуществующих полей.Могу поспорить, что лучше использовать приведение, ни пробелы!

select E.NAME, E.SURNAME, cast(null as varchar(20)) as CITY
from EMPLOYEE E

например, | Marc'O | Polo | <NULL> |

Это более точно, может определенно видеть размер поля, понятно, легко, безопасно!

1 голос
/ 28 апреля 2012

Если вы хотите объединить уже существующие «динамические» поля данных (со стороны провайдера) с дополнительными постоянными полями на стороне клиента (вычисляемые, поисковые, внутренние, вычисляемые, агрегированные), вы должны создать подкласс CDS.просто введите дополнительное логическое свойство CombineFields и либо переопределите BindFields (в ​​более новых версиях Delphi), либо весь InternalOpen (как я делал в d2006 / 2007) со следующей строкой

, если DefaultFields или CombineFields, то CreateFields;{TODO -ovavan -cSIC: если CombineFields равно true, то постоянные поля будут сосуществовать с полями по умолчанию}

, что позволит вам избежать всего этого беспорядка во время выполнения с FieldDefs / CreateField

...