Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 250
  • Last Modified:

Writing a Message/Record Log

I am writing an app and the user has requested that a LOG file be kept that shows ALL modifications made to each table. ie. Date, time, who made the change, table modified, actual data before change, data after modification, type of modification.

As there are approximately 20-30 tables that would need to be tracked, I thought that when a table is modified, I could call a single function which updated a LOG Table.

My question, where would be the best place to call the function or functions, ie. BeforeEdit, AfterEdit, OnUpdateRecord etc.

I understand that I would possibly have to call the function before and after updates to record previous data and new data.

Also, would I have to call this function from every table I modify, or is there a single place I could call it from.
0
pjelias
Asked:
pjelias
1 Solution
 
GreymanCommented:
I assume from your question that you are using TTable objects.

The easiest way to implement this would be to write a BeforePost handler to dump the change details of records that are being changed or added, and an AfterPost handler to confirm that the changed record was written successfully.

For deletions, you'll need to do the same sort of thing, using BeforeDelete and AfterDelete.

Note that you can get the previous value for a field using OldValue - you should also look into accessing the TField objects by number instead of name (this will allow you to use the same event handler on each table).

To implement this approach, you would need to hook up every table to the event handlers that you write (you should be able to reuse handlers, however).  You could do that using a custom component if you are comfortable with component writing, but I would avoid biting off more than I could chew ;)
0
 
FelixinCommented:
Are you using sql?

The use of trigger will make your application easier.
0
 
pjeliasAuthor Commented:
I am using Paradox tables with TTables (and wwTables - Infopower equivalent)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ITugayCommented:
Hi pjelias,

Easy way to solve you problem is to create your own TTable component derived from standard TTable. You can place all logic there (override DoBeforePost methods and so on). Then you need to replace all TTable in your project to your new TTable component.  Does it look like OOP? :-)

-----
Igor.

0
 
nnbbb09Commented:
Note that the OldValue property only works if you have CachedUpdates set to true
0
 
MoondancerCommented:
Is this the question you posted questions about in the Community Support Topic area?

Moondancer
Community Support Moderator @ Experts Exchange
0
 
pjeliasAuthor Commented:
ITugay,

could you please explain further, or provide an example
0
 
GreymanCommented:
Please note that ITugay's suggestion was covered in my suggestion:

"You could do that using a custom component if you
are comfortable with component writing, but I would avoid biting off more than I could chew ;) "

0
 
pjeliasAuthor Commented:
Sorry Greyman, I thought ITugay was talking about something else, didn't read comment fully.

I thought what you suggested would be the case, so I have tried to write code accordingly.

My problem is the following, what I want to be able to do is get the field names and values for the current record before edit, delete etc. and insert these into a Memo Field within my event log table.

I have got the theory and code basically working for a single table, the problem is trying to do this so that I can call the procedure/function from any table/dataset, by passing a few parameters, rather than attaching the same code to every table.

For example. If I have the following TTables, TableA, TableB, TableC and TableLOG, where TableLOG is the event LOG File with the following fields/types

DateTime  DateTime
UserID    Alphanumeric
TableName Alphanumeric
OldData   Memo

What I want to do is get the Field Contents of the Current Record for the current Table, which I add to a StringList and then insert in the EventLog OldData Memo field.
0
 
GreymanCommented:
Try this snippet:


var
  TempStrings : TStrings;
  Counter : integer;
begin
  TempStrings := TStringList.Create;
  try
    for Counter := 0 to DataSet.FieldCount - 1 do begin
      TempStrings.Add(DataSet.Fields[Counter].Name + '=' + DataSet.Fields[Counter].AsString);
    end;
    OldData := TempStrings;  // This only works if OldData is a TMemoField.
    OldData.AsString := TempStrings.CommaText;  //This will work for any char field.
  finally
    TempStrings.Free;
  end;
end;

Note that this is code for a TDataSetNotifyEvent - (such as BeforePost) these events take a parameter DataSet of type TDataSet.

I haven't handled null values in a sophisticated way, but I figure you can add that extension yourself.

HTH



Nick
0
 
pjeliasAuthor Commented:
Greyman,

thanks for that, but I actually worked it out before I read your response, see my code below


procedure TdMod.t2BeforeEdit(DataSet: TDataSet);
begin
  tName:=t2.TableName;
  GetData(DataSet,tName,'EDIT');
end;

procedure TdMod.t2BeforeDelete(DataSet: TDataSet);
begin
  tName:=t2.TableName;
  GetData(DataSet,tName,'DELETE');
end;

procedure TdMod.GetData(dSet: TDataSet; vTable,vType: String);
var sList: TStringList;
    fName,fVal,tName: String;
    fVar: Variant;
    i: Integer;
begin
  sList:=TStringList.Create;
  for i := 0 to dSet.FieldCount-1 do
  begin
    fName:=dSet.Fields[i].Name;
    if dSet.fields[i].IsIndexField then fName:=fName+'*';
    fVal:=dSet.Fields[i].AsString;
    sList.Add(fName+':= '+fVal);
  end;
  if not tLog.Active then tLog.Active:=True;
  tLog.InsertRecord([now,'userid',vTable,vType,sList]);
  sList.Free;
end;

Will give you the points anyway.

Thanks again
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now