Home Home Archives About red box
Username:
Password:
 
rss

Filed Under Delphi
digg Threaded Data Access
visits: 217 | score: 0 
posted by sysrpl on Tuesday August 21, 2007 1:12 PM

Visit my main Delphi page here

My friend Peter wrote asking about how I handle data access today. We had talked in the past about my objections to using business objects for data access. I replied to Peter with this message.

Regarding object frameworks for data binding, lately I've been building queries in the foreground by merging XML documents. Query operations are always executed in background threads. This has the effect of keeping the user interface quite snappy, and at the same time taking advantage of newer multi core architectures.

Queries are built automatically using custom XML schema documents. It's pretty much hands free. All I do is grab text values from controls with a little bit of custom code. A benefit of grabbing query parameters manuall is that I can use any control for data access, not just database aware controls. Below is a screen shot demonstrating this technique with my typical non-standard custom controls.

screenshot

The query statements are built by a custom TQueryBuilder class I designed. It works against two XML data documents, the first defining the fields and tables, the second defining how the tables relate to one another. Here is a fragment of what's in TQueryBuilder.Build:
  S := 'select';
  N := MergeFields.Root.FindNodes('//ROW');
  for I := 0 to N.Count - 1 do
  begin
    S := S + #13#10#9 + N.Node[I].Attributes.Filer.ReadString('FieldName');
    if I < N.Count - 1 then
      S := S + ',';
  end;
  S := S + #13#10'from';
  N := MergeJoins.Root.FindNodes('//ROW');
  for I := 0 to N.Count - 1 do
  begin
    S := S + #13#10#9;
    F := N.Node[I].Attributes.Filer;
    if I > 0 then
      S := S + Trim(F.ReadString('JoinType') + ' join') + ' ';
    S := S + F.ReadString('TableName');
    if F.ReadString('JoinOn') <> '' then
      S := S + ' on ' + F.ReadString('JoinOn');
  end;
  S := S + #13#10'where'#13#10#9'1 = 1';
This query is automatically fed to a data thread. The query results is returned as a string containing an XML document. It is passed back from the data thread through a messaging system. You registered a window with this messaging system once, then handle the thread events. Data events include OnStart, OnFinish, OnError, and OnProgressMessage.

I would typically grab the query result in the OnFinish event and store a private view of those results:
  Doc := CreateDocument;
  Doc.Text := (Sender as TDataThread).Result;
  FCustomerList := Doc.Root.FindNodes('//item');
Then later I can use thr result list to suit my needs. For example, to custom draw result text in a list box I use code like:
  F := FCustomerList.Node[Index].Attributes.Filer;
  DrawCaption(DC, F.ReadString('FIRST_NAME') + ' ' + F.ReadString('LAST_NAME'),
That's basically how it works. Let me know what you think.

print send topic Rate this article  

Title:

image link indent align right align middle align left quote underline bold code quote
Comment:

page generated in 0.078 seconds | last modified 2/06/2011 9:35 PM
none  none