2014-10-30 3 views
4

Для Delphi ClientDataSets, где поля были определены во время разработки, есть ли способ во время выполнения изменить тип данных определенного поля (изменить cds.Fields [n] .DataType)?Как изменить тип данных поля clientdataset во время выполнения

У меня есть устаревшая программа Delphi 7 с полями SQLDataSet и ClientDataSet, установленными во время разработки (чтобы переопределить различные свойства).

Они подключены к базе данных Sybase SQL Anywhere 11 третьей стороны.

Недавно продавец изменил все поля «Описание» от VarChar (128) до длинного varchar, но только для некоторых из его клиентов. Таким образом, мой код должен поддерживать оба типа полей, когда я запрашиваю эти поля «Описание».

Я надеялся установить условную компиляцию в типах классов классов (затем добавьте поля перед открытием набора данных SQL/CLient), но компилятор игнорирует условные выражения {$ IFDEF} в разделе определения компонентов класса (который, тем больше я думаю об этом, имеет смысл)!

Есть десятки модулей, в которых пострадали сотни полей, поэтому всякое понимание оценено.

Спасибо.

Приветствия, EDB

+3

Либо не добавляйте это поле до времени выполнения, а затем добавляйте соответствующий тип в эту точку или удаляйте его во время выполнения, если необходимо, и добавьте новый тип нужного вам типа. –

+0

Что сказал @KenWhite. Он должен работать нормально, но если у соответствующего поля (ов) есть аналог FieldDef, вам нужно удалить и воссоздать, иначе вы, вероятно, получите сообщение об ошибке, связанное с несоответствием между типом данных, определенным в FieldDef, и заменяющим TField когда вы открываете CDS. Лично я был бы склонен воссоздавать все поля/fielddefs, а не только те, которые были задействованы. – MartynA

+0

К сожалению, изменений в БД больше, чем я изначально думал - это может быть тысяча полей (в нескольких проектах). Он также имеет побочные эффекты - я широко использую DBgrids - я получаю (MEMO) вместо данных. Я могу установить OnGetText поля, но опять же, огромное количество полей ... CDS определены во время разработки, но я динамически создаю SQL - я думаю о том, чтобы просто делать CAST/Convert to VARCHAR в SQL. Хм, могут возникнуть проблемы с полями [n] .DataSize, например. - литье длинного varchar в поле, которое изначально было определено в CDS как VarChar [128] ... – edbored

ответ

1

Я также столкнулся с этой проблемой раньше, а не с CDS, но с TADODataSet используя постоянные поля во время разработки. Я думаю, что приведенный ниже код поможет вам понять, как исправить/исправить ваши наборы данных CDS.

Идея состоит в том, чтобы запросить соответствующую схему таблицы; получить фактический тип данных для файлов; и «изменение» настойчивый тип поля ипа-прикрепив ее из DataSet и добавление нового сопоставления настойчивых поданные вместо:

// TData class  
procedure TData.DataModuleCreate(Sender: TObject); 
var 
    I: Integer; 
begin 
    for I := 0 to ComponentCount - 1 do 
    if (Components[I] is TCustomADODataSet) then 
     DataSetPrepareMemoFields(TDataSet(Components[I])); 
end; 

procedure TData.DataSetPrepareMemoFields(DataSet: TDataSet); 
var 
    Fld: TField; 
    I: Integer; 
    FldName, CompName: string; 
    AOwner: TComponent; 
begin 
    // Here you need to query the actual table schema from the database 
    // e.g. ADOConnection.GetFieldNames and act accordingly 

    // check which DataSet you need to change 
    // if (DataSet = dsOrders) or ... then... 

    if DataSet.FieldList.Count > 0 then 
    for I := DataSet.FieldList.Count - 1 downto 0 do 
    begin 
     if DataSet.FieldList.Fields[I].ClassNameIs('TMemoField') and (DataSet.FieldList.Fields[I].FieldKind = fkData) then 
     begin 
     // save TMemoField properties 
     AOwner := DataSet.FieldList[I].Owner; 
     CompName := DataSet.FieldList[I].Name; 
     FldName := DataSet.FieldList.Fields[I].FieldName; 
     // dispose of TMemoField 
     DataSet.FieldList[I].DataSet := nil; // Un-Attach it from the DataSet 
     // create TWideADOMemoField instead 
     Fld := TWideADOMemoField.Create(AOwner); // Create new persistent Filed instead 
     Fld.Name := CompName + '_W'; 
     Fld.FieldName := FldName; 
     Fld.DataSet := DataSet; 
     end; 
    end; 
end; 

Тем не менее, после того как я исправил эту проблему, я никогда никогда снова использовал постоянные поля , Все мои поля генерируются во время выполнения. включая расчетные/поисковые/внутренние поля.

+0

Я уже закончил конверсию, но это выглядит интересно. Я вижу проблемы, основанные на том, что я ссылаюсь на поля посредством автоматических деклараций - например, в объявлении класса datamodule у меня есть myStringField: TStringField; и если я заменил тип данных, как указано выше, я думаю, что все еще могу видеть ошибки несовместимого типа. Мне понадобится неделя или около того, прежде чем я смогу вернуться к этому. На данный момент - спасибо! Это поможет мне продвигаться вперед. – edbored

Смежные вопросы