Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Database/Data Aware Controls/TDBLookupComboBox    [ Add a report in this area ]  
Report #:  5384   Status: Closed
TDBLookupComboBox Master/Detail problems
Project:  Delphi Build #:  4.453
Version:    7.0 Submitted By:   Sterling Butts
Report Type:  Basic functionality failure Date Reported:  7/25/2003 2:22:36 PM
Severity:    Critical / Show Stopper Last Updated: 3/20/2012 2:24:39 AM
Platform:    All versions Internal Tracking #:   192274
Resolution: Fixed (Resolution Comments) Resolved in Build: : D2005
Duplicate of:  None
Voting and Rating
Overall Rating: (2 Total Ratings)
5.00 out of 5
Total Votes: 10
Description
Errors happen when using a TDBLookupComboBox to display a list of data given by a detail TQuery. I can't get it to happen if the ListSource is not a detail. I believe there may be some problem with certain fields getting out of sync in a TDBLookupComboBox object. The Steps explain how to get the

"Field '' not found"

error but access violation errors happen as well.

This bug is the same bug reported by Gabriele Toccafondi report number 4823

I explain it here in more detail and have spent many hours to create a workaround because porting our programs to Delphi7 is a must.

I explain the error, steps to make the error, and workaround in more detail in the attachment called TDBLookupComboBoxFix in this report.
Steps to Reproduce:
1. Put the following items on a form

2 TQuery components
2 TDataSource components
2 TDBLookupComboBox components

2. Name them so the code generated looks something like this

    CustomerQuery: TQuery;
    CustomerSrc: TDataSource;
    CustomerComboBox: TDBLookupComboBox;
    OrdersQuery: TQuery;
    OrdersSrc: TDataSource;
    OrdersComboBox: TDBLookupComboBox;

3. Set these properties

CustomerQuery.DatabaseName  = DBDEMOS
CustomerQuery.Sql = SELECT * FROM customer
CustomerQuery.Active = true

CustomerSrc.DataSet = CustomerQuery

OrdersQuery.DatabaseName  = DBDEMOS
OrdersQuery.Sql = SELECT * FROM orders WHERE CustNo = :CustNo
OrdersQuery.Active = true

OrdersSrc.DataSet = OrdersQuery

CustomerComboBox.ListSource = CustomerSrc
CustomerComboBox.ListField = CustNo
CustomerComboBox.KeyField = CustNo

OrdersComboBox.ListSource = OrdersSrc
OrdersComboBox.ListField = OrderNo
OrdersComboBox.KeyField = OrderNo

OrdersQuery.DataSource  = CustomerSrc

4.Set the OrdersQuery.Params so the CustNo parameter's DataType = ftInteger and ParamType = ptInput

5. Run program

6. Select customer number 1231 from the CustomerComboBox

7. Press the dropdown arrow of the OrdersComboBox

At this point an error saying "OrdersQuery: Field '' not found" is given

I have attached a form called uTDBLookUpComboTestForm with these settings

I explain the error, steps to make the error, and workaround in more detail in the attachment called TDBLookupComboBoxFix in this report.
Workarounds
Make code changes in DBCtrls.pas by finding all places that referenced the following fields...

FDataField
FMasterField
FListField
FKeyField
and
FLookupMode

and replace them with functions that mimick the code that sets these fields in the first place. The new changed DBCtrls.pas is attached. Place this where a given program can find it in it's search path. After a full built the program should behave correctly. The attached DBCtrls.pas unit also contains the workaround given in report 3256 submitted by Clint Good. It may help report 1934 by Peter Broekhuizen as well.

I explain the error, steps to make the error, and workaround in more detail in the attachment called TDBLookupComboBoxFix in this report.
Attachment
5384.zip
Comments

. Analyst Programer at 12/7/2003 9:24:33 PM -
We are having the exact same problems.
Applied the fixed attached to this report, and all seems to work with the standard components. However, the same problem is evident when using the Rxlib TRxDBLookupCombo component. This is proving to be more difficult to fix however.

Jvrg Weingarten at 12/18/2003 3:55:57 PM -
Fix is in DB.pas. It got introduced fixing 117700.

To fix it do the following:

- Open Db.pas
- Go to "procedure TDataSet.DataEvent(Event: TDataEvent; Info: Longint);"
- In that procedure in the case statement for "deUpdateState:" add a "FEnabledEvent  := deLayoutChange;"
- Recompile your project with the new Db.pas.

Jvrg Weingarten at 12/18/2003 3:56:32 PM -

The code for the full "procedure TDataSet.DataEvent(Event: TDataEvent; Info: Longint);" is in attached small x.txt text file.

Jvrg Weingarten at 12/18/2003 3:58:17 PM -
Couldn't attach the file. Here is the code from the procedure:

procedure TDataSet.DataEvent(Event: TDataEvent; Info: Longint);

  procedure UpdateCalcFields;
  begin
    if State <> dsSetKey then
    begin
      if FInternalCalcFields and (TField(Info).FieldKind = fkData) then
        RefreshInternalCalcFields(ActiveBuffer)
      else if (FCalcFieldsSize <> 0) and FAutoCalcFields and
        (TField(Info).FieldKind = fkData) then
        CalculateFields(ActiveBuffer);
      TField(Info).Change;
    end;
  end;

  procedure NotifyDetails;
  var
    I: Integer;
  begin
    if Assigned(FNestedDataSets) then
    begin
      if State <> dsInsert then UpdateCursorPos;
      for I := 0 to FNestedDataSets.Count - 1 do
        with TDataSet(FNestedDataSets[I]) do
          if Active then DataEvent(deParentScroll, 0);
    end;
    if (State = dsBlockRead) then
      for I := 0 to FDataSources.Count - 1 do
        TDataSource(FDataSources[I]).NotifyLinkTypes(Event, Info, False);
  end;

  procedure CheckNestedBrowseMode;
  var
    I: Integer;
  begin
    if Assigned(FNestedDataSets) then
      for I := 0 to FNestedDataSets.Count - 1 do
        with TDataSet(FNestedDataSets[I]) do
          if Active then CheckBrowseMode;
  end;

var
  I: Integer;
  NotifyDataSources: Boolean;
begin
  NotifyDataSources := not (ControlsDisabled or (State = dsBlockRead));
  case Event of
    deFieldChange:
      begin
        if TField(Info).FieldKind in [fkData, fkInternalCalc] then
          SetModified(True);
        UpdateCalcFields;
      end;
    deFieldListChange:
      FieldList.Updated := False;
    dePropertyChange:
      FieldDefs.Updated := False;
    deCheckBrowseMode:
      CheckNestedBrowseMode;
    deDataSetChange, deDataSetScroll:
      NotifyDetails;
    deLayoutChange:
      begin
        FieldList.Updated := False;
        if ControlsDisabled then
          FEnableEvent := deLayoutChange;
      end;
    deUpdateState:
      if ControlsDisabled then
      begin
        Event := deDisabledStateChange;
        Info := Integer(State <> dsInactive);
        NotifyDataSources := True;
        FEnableEvent := deLayoutChange;
      end;
  end;

  if NotifyDataSources then
  begin
    for I := 0 to FDataSources.Count - 1 do
      TDataSource(FDataSources[I]).DataEvent(Event, Info);
    if FDesigner <> nil then FDesigner.DataEvent(Event, Info);
  end;

end;

Jvrg Weingarten at 1/6/2004 1:23:03 PM -
Actual Raid report number is 192274.

Server Response from: ETNACODE01