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

Having a problem with file server when using a different db

edited September 2003 in Server
If the file server is using the same database the report where designed
with, all works well. But, if I create a file server using a different
database name, get an error:
Server Error: processing request for Report Files\Members\test report
EDataError, TdaSession.GetDatgabaseForName: No TDatabase object found
for specified name, demo.
A Separate database connection is required for each thread.

I thought the rbReportTemplateVolume unit owned the reports and the
reports used the db connection in the rbReportTemplateVolume unit. The
database object connects correctly and I can design a report in the ide
with the connections. Just can't run a report from a client app.

Is there something more that needs to be done before a report is run
when using a different database?

Thanks,
Dave

Comments

  • edited September 2003

    When you create a report using the Data workspace, the DatabaseName is
    saved as part of the report definition. When the report loads, there
    needs to be a connection component (i.e. TDatabase when using the BDE)
    with the same name.


    The article below is not specific to server applications, but is
    applicable here....


    -------------------------------------------------
    Tech Tip: How to modify the DatabaseName stored
    with a DADE Query
    -------------------------------------------------

    Currently when DADE is used to create dataviews,
    the DatabaseName is stored as part of the query
    definition. (This is consistent with Delphi's
    approach to specifying a database connection for
    a Query object).

    In some cases, you may decide that the
    DatabaseName needs to be modified at a later date.

    We recommend that the DatabaseName
    refer to a TDatabase connection component or to
    an Alias to provide flexibility for changing
    the connection parameters.

    A second way to handle this issue is to implement
    some code that specifies a DatabaseName
    whenever a template is loaded. This can be accomplished
    by using the Report.Template.OnLoadEnd event.


    1. Declare an event-handler procedure in the private
    section of your form declaration.

    type
    myForm = class(TForm)
    private
    procedure ReportTemplateLoadEndEvent(Sender: TObject);
    public
    end;


    2. Use the FormCreate event to assign the event-handler to
    the event property.

    procedure myForm.FormCreate(Sender: TObject)
    begin
    Report1.Template.OnLoadEnd := ReportTemplateLoadEndEvent;

    end;

    3. Add code to the event-handler to specify the database name.


    procedure myForm.ReportTemplateLoadEndEvent(Sender: TObject)
    var
    lSQL: TdaSQL;

    begin
    if GetSQLObject(Report1, lSQL) then
    begin
    lSQL.DatabaseName := Designer.DataSettings.DatabaseName;
    SetSQLObject(Report, lSQL);
    lSQL.Free;

    end;

    end;


    4. Below is a tech tip for extracting the SQL object
    from a report. TdaSQL is a class defined in daQClass.pas.

    -------------------------------------------------
    Tech Tip: How to access the SQL object associated
    with a Report created using DADE
    -------------------------------------------------

    uses
    daDatMod;


    function GetSQLObject(aReport: TppReport; var aSQL: TdaSQL): Boolean;
    var
    lDataModule: TdaDataModule;
    lDataView: TdaDataView;
    begin

    aSQL := TdaSQL.Create(nil);

    {get the datamodule}
    lDataModule := daGetDataModule(aReport);

    if (lDataModule <> nil) then
    begin
    lDataView := lDataModule.DataViews[0];

    if (lDataView <> nil) and (lDataView is TdaQueryDataView) then
    aSQL.Assign(TdaQueryDataView(lDataView).SQL);

    end;

    Result := (aSQL <> nil);

    end;


    procedure SetSQLObject(aReport: TppReport; aSQL: TdaSQL);
    var
    lDataModule: TdaDataModule;
    lDataView: TdaDataView;
    begin


    {get the datamodule}
    lDataModule := daGetDataModule(aReport);

    if (lDataModule <> nil) then
    begin
    lDataView := lDataModule.DataViews[0];

    if (lDataView <> nil) and (lDataView is TdaQueryDataView) then
    TdaQueryDataView(lDataView).SQL := aSQL;

    end;

    end;





    --
    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 September 2003
    In using the ReportTemplateVolume ValidateReportParameters event as the
    trigger to get the report to set the database name, I can not find the
    Report.Template.OnLoadEnd event. This is where I get thoughly
    confussed. I've used the below procedure to change the database name
    for EUR reports, but I can not figure how to add the same event to the
    server modules.
    I'v used:
    procedure
    TdmReportTemplateVolume.rsReportTemplateVolume1ValidateReportParameters(
    Sender: TObject; aEventParams: TrsValidateReportParametersEventParams);
    begin
    TppReport(aEventParams.Report).Template.OnLoadEnd :=
    ReportTemplateLoadEndEvent;
    end;
    This gets set, but the report event does not fire and I get the same error.

    Also, is the Sender in ReportTemplateLoadEndEvent(Sender: TObject)
    the report object so I can use TppReport(Sender).Template instead of
    Report1?

    I'm really struggeling with the server objects as to when they are
    actually loaded to send to the client and I can add my events to do my
    special processing. I've also tried to add the report event in the
    BeforePublishReport event. I guess I need some help.

    Thanks,
    Dave


  • edited September 2003
    I was able to change the database name if I used the
    TrsReportTemplateVolume OnLoadReportEnd as:
    procedure TdmReportTemplateVolume.rsReportTemplateVolume1LoadReportEnd(
    Sender: TObject);
    var
    lSQL: TdaSQL;
    begin
    if GetSQLObject(TppReport(Sender), lSQL) then
    begin
    lSQL.DatabaseName := Sessions.CurrentSession.Databases[0].databaseName;
    SetSQLObject(TppReport(Sender), lSQL);
    end;
    end;

    But I had to change the SetSqlObject to:
    procedure TdmReportTemplateVolume.SetSQLObject(aReport: TppReport; aSQL:
    TdaSQL);
    var
    lDataModule: TdaDataModule;
    lDataView: TdaDataView;
    begin
    {get the datamodule}
    lDataModule := daGetDataModule(aReport);

    if (lDataModule <> nil) then
    begin
    lDataView := lDataModule.DataViews[0];

    if (lDataView <> nil) and (lDataView is TdaQueryDataView) then
    TdaQueryDataView(lDataView).SQL.DatabaseName := aSQL.DatabaseName;
    // TdaQueryDataView(lDataView).SQL := aSQL;
    end;
    end;

    If I used the aSql to set the ~.SQL there is an error that there is no
    sql. Changing just the database name works for now. But I still would
    like more info on the what objects are load when.

    Thanks,
    Dave


  • edited September 2003

    This is the appropriate event to use. For ReportVolumes you want to use
    ReportVolume.OnLoadReportEnd event rather than
    Report.Template.OnLoadEnd.




    Best regards,

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