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

TClient datasets on a RBServer

edited August 2006 in General
Converted several client/server reports from Delphi 5 and RB to web based
reports using Delphi 2006 and the latest RBServer. We went with form based
reports for an easy transition of our old reports into the new environment.
I have one report that used a string grid to build the data for the report
and used a jitpipeline. The converted report worked fine as long as only
one person ran the report, but when a second user ran the same report the
RBServer would fail. Tried several things to isolate/lock the code, but
nothing seemed to help. Then I tried using a TClient dataset, it too works
great in the single user environment. Even better than the string grid
because it was so straight forward. Real simple to understand what was
happening. Loved the simplicity creating, loading, editing, and sorting of
the TClient dataset, however when multiple reports are run on the server it
is very easy to tell that each time the report is run, that all iterations
of the same report are sharing the dataset, sometimes when the reports are
displayed the data from one report is displayed on another report.

I need to read data from several sources (that part is done) , do some
editing and calculation in the code, sort the data, and send it to the
report. What is the best way to do this. I have thought of building an
array, but the TClient dataset was so simple and clear-cut, just doesn't
work on the server. Usually only a handful of records, 10 or 20 for each
report, but could be upwards of 1,000 (name, SSAN, class,...)

Thanks for the help.

Ron Hagan

Comments

  • edited August 2006

    This issue was also emailed to support@digital-metaphors.com and has been
    solved.

    The problem was caused by using unit level variables. Unit level variables
    are global variables. They are not thread-safe and even in a single threaded
    environment, can produce incorrect results if multiple instances of a class
    try to use them for instance level information.

    Below is a simple example. In the example, each instance of the TmyForm
    class will have its own copy of instance variable FCount. However, for the
    unit level variable, uCount, there is only one copy. Thus if TmyForm stores
    results to uCount, multiple form instances will interfere with each other.

    unit myUnit;

    interface

    TmyForm = class(TForm)
    private
    FCount: Integer; // instance variable - thread-safe
    public
    end;

    var
    uCount: Integer; // unit level variable - not thread-safe

    implementation


    end;






    --
    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com


    Best regards,

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