Я хотел создать новый файл MDB, содержащий таблицы, основанные на структуре ранее существующих таблиц.Я знал, что могу использовать newTable.FieldDefs.Add()
для воссоздания полей одно за другим в цикле.Но поскольку уже существует старая таблица, полностью заполненная правильным FieldDefs
, это казалось ужасно не элегантным.Я искал решение с одним утверждением!
Я обнаружил, что newTable.FieldDefs.Assign(oldTable.FieldDefs)
будет компилироваться (и запускаться) без ошибок, но он оставил newTable
с нулевыми полями.Это заставило меня ошибочно заключить, что я не понял функцию этого утверждения.(Позже я обнаружил, что сбой произошел только тогда, когда oldTable.open
не произошло, чего не могло произойти, если база данных была недоступна, даже если FieldDefs
был сделан постоянным и был четко виден в Инспекторе объектов)
Вот мой оригинальный код после некоторой проверки:
procedure TForm2.Button1Click(Sender: TObject);
var
fname: string;
Table: TFDTable;
FDConn: TFDConnection;
begin
fname := 'C:\ProgramData\mymdb.mdb';
if FileExists(fname) then DeleteFile(fname);
{ Make new file for Table }
FDMSAccessService1.Database := fname;
FDMSAccessService1.DBVersion := avAccess2000;
FDMSAccessService1.CreateDB;
{ Connect to new file }
FDConn := TFDConnection.Create(nil);
FDConn.Params.Database := fname;
FDConn.Params.DriverID := 'MSAcc';
FDConn.Connected := true;
{ Set up new Table using old table's structure }
Table := TFDTable.Create(nil);
try
{ ADOTable1 has been linked to an existing table in a prior
database with Field Defs made Persistent using the Fields
Editor in the Object Inspector. That database will not be
available in my actual use scenario }
try
ADOTable1.open; // Throws exception when database file not found
except
end;
Table.Connection := FDConn;
{ specify table name }
Table.TableName := ADOTable1.TableName;
Table.FieldDefs.Assign(ADOTable1.FieldDefs); // No errors reported
ShowMessageFmt('New Table %s has %d fields',[Table.TableName,
Table.FieldDefs.Count]);
{ Reports correct TableName but "0 fields" with table not open
(i.e. file not found). Reports "23 fields" with table open }
{ Set Table definition into new mdb file }
Table.CreateTable(False); // Throws exception when 0 fields found
finally
Table.Free;
end;
end;
Оказалось, что решение было использовать ClientDataSet, первоначально связанный с той же старой базой данных, вместо ADOTable.См. Рабочее решение ниже в моем ответе.
Редактировать: Последнее замечание.Я надеялся использовать этот подход FireDAC, как указано здесь, чтобы обойти отсутствие метода TADOTable.CreateTable
.Увы, хотя «решения» выше и ниже действительно работают для создания нового TADOTable
, определения полей этой таблицы не являются точными копиями исходной таблицы.Это может быть сочетание множества опций TFDTable
, которые могут обойти это, но я не смог обнаружить его, поэтому я вернулся к созданию таблиц ADO с SQL.