Home General
New Blog Posts: Merging Reports - Part 1 and Part 2

TMasterFieldLinks

edited December 2005 in General
What is the appropriate method for creating, setting the owner, and freeing
a TMasterFieldLink at runtime?

I need to setup the link between the two data pipelines at runtime. However
when I close the program I get an access violation. Since the
TMasterFieldLink has an owner, I thought the owner would handle destroying
the link am I wrong?

Bill

Comments

  • edited December 2005

    Try using the following example...


    ---------------------------------------------------------
    Tech Tip: Define Master/Detail DataPipeline Links in Code
    ---------------------------------------------------------

    Defining a Master/Detail relationship for a DataPipeline
    requires that the detail pipeline have the
    following properties defined:

    1. MasterDataPipeline

    2. MasterFieldLinks


    At Delphi design-time you can use the object inspector
    and the DataPipeline's FieldLinks editor to define
    the master/detail relationship.


    The following example illustrates how to define the
    master/detail relationship dynamically at run-time.


    var
    lFieldLink: TppMasterFieldLink;


    begin

    {define the master/detail pipeline relationship}
    plDetail.MasterDataPipeline := plMaster;

    {create a new field link }
    lFieldLink := TppMasterFieldLink.Create(nil);

    lFieldLink.Parent := plDetail;

    {assign the detail field name}
    lFieldLink.DetailFieldName := 'CustNo';

    {assign the master field name}
    lFieldLink.MasterFieldName := 'CustNo';


    end;


    Note: The DataPipeline linking requires the records in the detail dataset to
    be ordered by the linking fields. In the above example, the detail data must
    be ordered by CustNo.


    --
    Tech Support mailto:support@digital-metaphors.com
    Digital Metaphors http://www.digital-metaphors.com




    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited December 2005
    Don't we need the following line?

    plDetail.AddChild(lFieldLink);


  • edited December 2005

    No, that will cause an AV on the destroy. Setting the FieldLink.Parent
    property will cause it to be added to the pipeline. (Internally an
    appropriate destroy notification relationship will established and AddChild
    will be called).

    lFieldLink.Parent := plDetail;





    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • edited December 2005
    Here comes a more detailed problem.

    Whenever I try to create a report and creating a master-child in code the
    report comes up blank if I place any child pipeline fields in a subreport.
    Here is the code I use to create the dataset, datasource and pipelines. It
    works fine on basic pipeline reports. Even reports with multiple pipelines,
    but once I try to do a master-child report (which I have added to the
    method) it doesn't work.

    procedure TfmDynReports.CreatePipe(PipeSQL: String; PipeID, MasterID:
    Integer; MC_Mapping: String);
    var
    PipeQuery: TMSQuery;
    PipeDataSource: TDataSource;
    PipePipeline: TppDBPipeline;
    m: TppMasterFieldLink;
    i: Integer;
    s: String;
    begin
    PipeQuery := TMSQuery.Create(Self);
    PipeQuery.Name := Format('PipeQuery%d', [PipeID]);
    PipeQuery.Connection := dmMain.dbInstitution;
    PipeQuery.SQL.Text := PipeSQL;
    PipeQuery.Active := True;
    CreatedItems.Add(PipeQuery.Name);

    PipeDataSource := TDataSource.Create(Self);
    PipeDataSource.DataSet := PipeQuery;
    PipeDataSource.Name := Format('PipeDataSource%d', [PipeID]);
    CreatedItems.Add(PipeDataSource.Name);

    PipePipeline := TppDBPipeline.Create(Self);
    PipePipeline.DataSource := PipeDataSource;
    PipePipeline.Name := Format('PipePipeline%d', [PipeID]);
    CreatedItems.Add(PipePipeline.Name);
    //setup master child if exists
    {the master-child relationship is setup by doing the following
    First - The master data pipeline is identified by identifying the
    sql_order
    value of the master pipeline. -1 in this value means there is no
    master datasource
    Second - The master - child field mappings are identified by the
    following format: MASTER=CHILD
    To add multiple master - child field mappings separate the
    mappings with a semicolon like such:
    MASTER=CHILD;MASTER=CHILD.
    }
    if MasterID <> -1 then
    begin
    PipePipeline.MasterDataPipeline :=
    TppDBPipeline(FindComponent(Format('PipePipeline%d' , [MasterID])));
    for i := 1 to ListLen(MC_Mapping, ';') do
    begin
    m := TppMasterFieldLink.Create(nil);
    m.Name := Format('MasterFieldLink%d_%d', [PipeID, i]);
    CreatedItems.Add(m.Name);
    m.Parent := PipePipeline;
    s := ListGetAt(MC_Mapping, i, ';');
    m.MasterFieldName := ListGetAt(s, 1, '=');
    m.DetailFieldName := ListGetAt(s, 2, '=');
    end;
    end;
    end;

    Bill
  • edited December 2005

    1. Make sure that the detail query data is ordered by the linking fields (in
    the exact same order).

    2. I cannot determine what is happening by looking at that code. I would
    approach something like this incrementally. Create a simple master detail
    report at Delphi design-time - for example Customer/Orders using DBDemos.
    Link the pipelines using the field links editor. Once it is working
    correctly, then incrementally start converting the data access pieces to
    code. First implement the pipeline creation and linking. Then run and test
    until it works. Next implement the DataSource creation. Run and test. Then
    implement the Query creation in code. Once all that is working, then create
    the more general purpose routines. If you use DBDemos as a starting point,
    then if you get stuck you can zip it up and send to
    support@digital-metaphors.com and we can run it here in the debugger.





    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
This discussion has been closed.