Delphi7,dbExpress和主从关系

3
我是Delphi的新手。我有两个TSQLTables(称为A和B),分别通过两个TDataSetProviders连接到两个TClientDataSets(称为cdsA和cdsB)。两个DataSources(dsA和dsB)完成了场景。
让A成为主要的,让B成为详细的。
将B.MasterSource设置为dsA值,并且B.MasterFields值引用一个在cdsA中不存在的字段(但在查询中存在)。当我启动应用程序时,我首先打开cdsA,然后打开cdsB。出了些问题。链接到dsA数据源的DBGrid显示数据,链接到dsB的DBGrid不显示任何内容。 SQLMonitor日志文件显示在B中实现的查询被执行(一个简单的select a,b,c from tableB)。如果我更改查询并显示字段'X'(select a,b,c,X from tableB),则一切正常。
为什么链接到dsB的DBGrid不显示与cdsA当前记录相关的B记录?只有在查询列中指定IndexFieldNames时才有效吗?我错过了什么? TIA.
2个回答

2
我将使用 AdventureWorks 数据库来解释完整的场景,该数据库适用于 SQL Server 2008 R2。我还假设您已经放置了 TSQLConnection 组件并正确设置了其参数以与您的数据库建立连接。对于此示例,我还假设其名称为 Conn1
在表单上,放置 2 个 TSQLTable(命名为 tableAtableB)、2 个 TDataSetProvider(命名为 dspAdspB)、2 个 TClientDataSet(命名为 cdsAcdsB)、2 个 TDataSource(命名为 dsAdsB)和 2 个 TDBGrid(命名为 gridAgridB)组件。
设置属性如下:
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 中,您只能看到当前选择的客户相关的订单。
这是在Delphi中在两个TClientDataSet组件之间建立主/细节关系的基本示例。但是,还有其他方法可以实现此目的。

我认为问题在查询中。使用dbExpress,我必须在查询的列集中指定外键字段,而不仅仅是在where子句中。这是真的吗?如果(正如我所希望的)不是这样,那我错过了什么? - Francesco
不,你不必这样做。我建议你开始一个新项目并重新创建我所解释的内容。这可能有助于你完全理解如何在Delphi中正确建立主/从关系。此外,请查看数据库本身。表的结构可以帮助你进一步了解外键的工作原理,并可能指出数据库设计中可能存在的问题。 - LightBulb
如果我不指定IndexFieldNames的值,就会出现“字段索引超出范围”的错误。如果是TabA JOIN TabB on a = b,我必须将b指定为详细信息的IndexFieldNames属性的值。否则,网格将不显示任何内容。我使用Vista、Delphi7、Oracle11g和Devart dbExpress驱动程序(版本4.70)。 - Francesco
您不必使用 JOIN 连接这些表。每个表都在其自己的 TSQLTable 组件中单独查询,然后使用 MasterSourceMsterFields 属性将它们“连接”以形成主/细节关系。除非您正在尝试更复杂的操作,否则不需要其他任何操作来建立简单的关系。 - LightBulb

0
我连接ClientDataSets的方式在Cary Jensen的书《Delphi In Depth: Client DataSets》中有详细说明。按照正常流程设置主数据集和详细数据集,并确保它们通过TDataSource链接(您将在详细SQL中有一个参数将其链接到主数据集)。然而,CJ建议只有一个DataSetProvider附加到主数据集。但是主数据集(因此DSP)将具有表示详细表的嵌套数据集。详细/嵌套数据集可以出现在主表DBGrid或自己的DBGrid中。您的gridB将链接到嵌套数据集。
直接将gridB链接回TSQLQuery的问题是,对主CDS的任何更新都不会反映在gridB中。如果您想了解更多信息,则可以从Cary的网站下载项目NestedFromMasterDetail。
如果您真的想了解更多,请购买Cary的书。我发现它在理解客户端数据集方面非常有价值。它们的设置有些不同,Cary做了很好的工作来解释它们的架构。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接