【问题标题】:Delphi7, dbExpress and Master Detail relationshipDelphi7、dbExpress和Master Detail关系
【发布时间】:2011-11-21 17:34:51
【问题描述】:

我是德尔福的新手。我有两个 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),这些东西就可以正常工作,其中“X”是 B.IndexFieldNames 属性引用的字段。

为什么链接到 dsB 的 DBGrid 没有显示与 cdsA 的当前记录相关的 B 记录?仅当我在查询列中指定 IndexFieldNames 时它才有效吗?我错过了什么? TIA。

【问题讨论】:

    标签: delphi delphi-7 master-detail dbexpress


    【解决方案1】:

    我将使用 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 中您应该看到所有 Customers,在 gridB 中您应该只看到与当前相关的 Orders选定的客户。

    这是在 Delphi 中建立两个 TClientDataSet 组件之间的主/从关系的基本示例。但是,还有其他方法可以做到这一点。

    【讨论】:

    • 我认为问题在于查询。使用 dbExpress 我必须在查询的列集中指定外键字段,而不仅仅是在它的 where 子句中。这是真的?如果(如我所愿)不是我错过了什么?
    • 不,您不必这样做。我建议您开始一个新项目并重新创建我已经解释过的内容。这可能会帮助您充分了解如何在 Delphi 中正确建立主/从关系。另外,看看数据库本身。表的结构可以帮助您进一步了解外键的工作原理,并可能指出您数据库设计中可能存在的问题。
    • 如果我没有指定IndexFieldNames 值,我会得到field index out of range。如果TabA JOIN TabB on a = b,我必须将b 指定为详细信息的IndexFieldNames 属性的值。如果不是,网格不会显示任何内容。我在 Vista、Delphi7、Oracle11g、Devart dbExpress 驱动程序(4.70 版)上工作。
    • 您不必JOIN 这些表。每个表在其自己的TSQLTable 组件中单独查询,然后使用MasterSourceMsterFields 属性将它们“连接”以形成主/详细 关系。除非您尝试更复杂的事情,否则简单的关系不需要其他任何东西。
    【解决方案2】:

    Cary Jensen's book "Delphi In Depth: Client DataSets" 中概述了我链接 ClientDataSets 的方式。照常设置 Master 和 Detail 数据集,并确保它们通过 TDataSource 链接(您将在 Detail SQL 中有一个参数将其链接到 Master)。但是,CJ 建议只有一个附加到主服务器的 DataSetProvider。但是主服务器(以及因此的 DSP)将有一个嵌套数据集来重新表示详细信息表。详细/嵌套数据集可以出现在主表 DBGrid 或它自己的 DBGrid 中。您的 gridB 将链接到嵌套数据集。

    将 gridB 直接链接回 TSQLQuery(据我所知)的问题是对主 CDS 的任何更新都不会反映在 gridB 中。如果您想查看更多内容,可以从 Cary 的网站下载 NestedFromMasterDetail 项目。

    如果你真的想了解更多,那就买一本 Cary 的书吧。我发现它对于理解客户端数据集非常宝贵。它们的设置有些不同,Cary 很好地解释了它们的架构。

    【讨论】:

      猜你喜欢
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多