Связь Delphi7, dbExpress и Master Detail

Я новичок в Делфи. У меня есть две таблицы TSQLTable (скажем, A и B), связанные с двумя TClientDataSet (скажем, cdsA и cdsB соответственно) двумя TDataSetProviders, два источника данных (dsA и dsB) завершают сценарий.

Пусть А будет главным, а Б — подробным.

B.MasterSource имеет значение dsA, а значение B.MasterFields относится к полю, которого нет в cdsA (но существует в запросе). Когда я запускаю приложение, я сначала открываю cdsA, а затем открываю cdsB. Что-то идет не так. DBGrid, который ссылается на источник данных dsA, показывает данные, DBGrid, который ссылается на dsB, ничего не показывает. Файл журнала SQLMonitor показывает, что запрос, реализованный в B, выполняется (простой select a, b, c from tableB ). Материал работает нормально, если я изменяю запрос и показываю поле «X» (select a, b, c, X from tableB), где «X» — это поле, на которое ссылается свойство B.IndexFieldNames.

Почему DBGrid, который ссылается на dsB, не показывает запись B, связанную с текущей записью cdsA? Это работает, только если я укажу IndexFieldNames в столбцах запроса? Что я пропустил? ТИА.


person Francesco    schedule 21.11.2011    source источник


Ответы (2)


Я объясню весь сценарий, используя базу данных AdventureWorks для SQL Server 2008 R2. Я также предполагаю, что вы уже разместили компонент TSQLConnection и правильно установили его параметры для установления соединения с вашей базой данных. В этом примере я также предполагаю, что это имя будет Conn1.

В форму поместите 2 TSQLTable (с именами tableA и tableB), 2 TDataSetProvider (с именами dspA и dspB) , 2 TClientDataSet (с именами cdsA и cdsB), 2 TDataSource (с именами dsA и dsB) и 2 TDBGrid (с именами именованные компоненты gridA и gridB).

Установите свойства следующим образом:

tableA.SQLConnection = Conn1
tableA.SchemaName = Sales
tableA.TableName = Customer
tableA.Active = True

dspA.DataSet = tableA

cdsA.ProviderName = dspA
cdsA.Active = True

dsA.DataSet = cdsA

gridA.DataSource = dsA

tableB.SQLConnection = Conn1
tableB.SchemaName = Sales
tableB.TableName = SalesOrderHeader
tableB.Active = True

dspB.DataSet = tableB

cdsB.ProviderName = dspB
cdsB.MasterSource = cdsA
cdsB.MasterFields = CustomerID
cdsB.Active = True

dsB.DataSet = cdsB

gridB.DataSource = dsB

В gridA вы должны увидеть всех Клиентов, а в gridB вы должны увидеть только Заказы, относящиеся к выбранному в данный момент клиенту.

Это базовый пример установления связи master/detail между двумя компонентами TClientDataSet в Delphi. Однако есть и другие способы сделать это.

person LightBulb    schedule 22.11.2011
comment
Я думаю, что проблема остается в запросе. Используя dbExpress, я должен указать поле внешнего ключа в наборе столбцов запроса, а не только в предложении where. Это правда? Если (как я надеюсь) не то, что я пропустил? - person Francesco; 22.11.2011
comment
Нет, вам не нужно этого делать. Я бы посоветовал вам начать новый проект и воссоздать то, что я объяснил. Это может помочь вам полностью понять, как правильно установить отношения master/detail в Delphi. Также обратите внимание на саму базу данных. Структура таблиц может помочь вам лучше понять, как работают внешние ключи, и может указать на возможную проблему в дизайне вашей базы данных. - person LightBulb; 22.11.2011
comment
Если я не укажу значение IndexFieldNames, я получу field index out of range. Если TabA JOIN TabB on a = b, я должен указать b в качестве значения свойства IndexFieldNames детали. Если нет, сетка ничего не показывает. Работаю на Vista, Delphi7, Oracle11g, драйвер Devart dbExpress (версия 4.70). - person Francesco; 24.11.2011
comment
Вам не нужно JOIN эти таблицы. Каждая таблица запрашивается отдельно в своем собственном компоненте TSQLTable, а затем они "соединяются" для формирования отношения главный/подробности с использованием свойств MasterSource и MsterFields. Для простого отношения больше ничего не требуется, если только вы не пытаетесь сделать что-то более сложное. - person LightBulb; 24.11.2011

Способ связывания ClientDataSets описан в книге Кэри Дженсен "Delphi In Depth: Client DataSets". Настройте наборы данных Master и Detail как обычно и убедитесь, что они связаны через TDataSource (у вас будет параметр в Detail SQL, который связывает его с Master). Тем не менее, CJ предлагает иметь только один DataSetProvider, который подключен к Мастеру. Но мастер (и, следовательно, DSP) будет иметь вложенный набор данных, повторно представляющий подробную таблицу. Детальный/вложенный набор данных может отображаться в основной таблице DBGrid или в собственной DBGrid. Ваш gridB будет связан с вложенным набором данных.

Проблема при прямом связывании gridB с TSQLQuery (насколько я понимаю) заключается в том, что любые обновления главной CDS не отражаются в gridB. Если вы хотите увидеть больше, вы можете загрузить проект NestedFromMasterDetail с веб-сайта Кэри.

Если вы действительно хотите узнать больше, купите экземпляр книги Кэри. Я нашел его неоценимым для понимания клиентских наборов данных. Они настроены несколько иначе, и Кэри хорошо объясняет их архитектуру.

person DavidG    schedule 22.11.2011