Mega Search
23.2 Million


Sign Up

Make a donation  
TClientDataSet - Key Violation - I have no idea how to solve  
News Group: embarcadero.public.delphi.database.interbase_express

Greetings All,

Recently upgraded to Delphi XE5 from Delphi 5.  The following code worked fine in a Delphi 5 project since 1999.  Now that it is compiled under Delphi XE5 I get a Key Violation.

TDataSource -> TClientDataSet -> TDataProvider -> TIBQuery

The source code segment shown below creates a temp ClientDataset that will hold data that will eventually be sent to a data file for Word Perfect.

Here is the basic concept of how this works.

There are two main and one temp ClientDatasets:
cdsBatchPrintItem - DataSet containing among others fields ACCT_ID, CASE_ID and NO_OF_COPIES_TO_PRINT.  This dataset is looped thru to pull data into cdsMergeCase
cdsMergeCase -  Dataset that pulls all relevent data for an account/case
cdsTemp - A temporary ClientDataSet that is cloaned from cdsMergeCase and is used to hold all records that will be eventually merge to Word Perfect.  This dataset can hold duplicates of the same record returned in cdsMergeCase based on the cdsBatchPrintItem.NO_OF_COPIES_TO_PRINT value.

cdsMergeCase has an empty TIBQuery.SQL and there are no persistent fields on either the TIBQuery or the TClientDataset.  In other words a dummy dataset that can contain any custom SQL set in the TClientDataSet.CommandText

Here is the dynamically created SQL for cdsMergeCase:

SELECT CAST(0 AS SmallInt) AS Selected,
COALESCE(COMPANY.COMPANY_NAME || ' #' || BN.BAR_NO, COMPANY.COMPANY_NAME) AS CompanyName,
COMPANY.ADDRESS1 AS CompanyAddress1,
COMPANY.ADDRESS2 AS CompanyAddress2,
Z.CITY || ', ' || Z.STATE_CODE || ' ' || Z.ZIP_CODE AS CompanyCityStateZip,
Z.CITY || ' ' || Z.STATE_CODE || ' ' || Z.ZIP_CODE AS CompanyCityStateZipNC,
'('|| COMPANY.TOLL_FREE_PHONE_AREA_CODE ||') '|| COMPANY.TOLL_FREE_PHONE_NO AS CompanyTollFreePhone,
'('|| COMPANY.PHONE_AREA_CODE ||') '|| COMPANY.PHONE_NO AS CompanyPhone,
'(' || COMPANY.FAX_AREA_CODE || ') ' || COMPANY.FAX_NO AS CompanyFax,
ACCOUNT.ACCT_ID || '-' || CA.CASE_ID AS AccountRefNo,
ACCOUNT.ACCT_ID AS AccountID,
CA.CASE_ID AS CaseID,
CLIENT.CLT_ID AS ClientID,
CLIENT.CLIENT_CODE AS ClientCode,
CLIENT.NAME AS ClientName,
CLIENT.DBA AS ClientDBA,
CLIENT_SITE.CLT_SITE_ID AS ClientSiteID,
CLIENT_SITE.SITE_REF_NO AS ClientSiteRefNo,
CLIENT_SITE.SITE_NAME AS ClientSiteName,
CNTY.COUNTY_CODE AS FilingCountyCode,
CNTY.NAME AS FilingCountyName,
CNTY.STATE AS FilingCountyStateCode,
S.NAME AS FilingCountyStateName,
CNTY.COURT_NAME AS FilingCountyCourtName,
CNTY.COURT_ADDRESS1 AS FilingCountyCourtAddress1,
CNTY.COURT_ADDRESS2 AS FilingCountyCourtAddress2,
Z2.CITY || ', ' || Z2.STATE_CODE ||' ' || Z2.ZIP_CODE AS FilingCountyCourtCityStateZip,
Z2.CITY || ' ' || Z2.STATE_CODE ||' ' || Z2.ZIP_CODE AS FilingCtyCourtCityStZipNC,
CA.ORIG_FEE + CA.ADJ_FEE AS OriginalCaseFee,
CA.ORIG_FEE + CA.ADJ_FEE - CA.PAID_FEE AS CaseFeeBalance,
CA.POST_JUDGMENT_ACCRUED_INTEREST + CA.POST_JUDGMENT_ADJ_INTEREST - CA.POST_JUDGMENT_PAID_INTEREST AS CasePostJudInterestBalance,
CA.POST_JUDGMENT_ACCRUED_INTEREST + CA.POST_JUDGMENT_ADJ_INTEREST AS CasePostJudInterest
FROM ACCT_CASE CA
     INNER JOIN COMPANY ON (CA.CUR_COMPANY_ID = COMPANY.COMPANY_ID)
     INNER JOIN ACCOUNT ON (ACCOUNT.ACCT_ID = CA.ACCT_ID)
     INNER JOIN COUNTY CNTY ON (CNTY.COUNTY_ID = CA.FILING_COUNTY_ID)
LEFT OUTER JOIN COMPANY_STATE_OWNER_BAR_NO BN ON BN.COMPANY_ID = COMPANY.COMPANY_ID
AND BN.STATE_CODE = CNTY.STATE
     INNER JOIN STATE S ON S.STATE_CODE = CNTY.STATE
     INNER JOIN DEBT ON (CA.ACCT_ID = DEBT.ACCT_ID) and (CA.CASE_ID = DEBT.CASE_ID)
     INNER JOIN DEBT_TYPE ON (DEBT.DEBT_TYPE_CODE = DEBT_TYPE.DEBT_TYPE_CODE)
     INNER JOIN CLIENT ON (CA.CLT_ID = CLIENT.CLT_ID)
     INNER JOIN CLIENT_SITE ON (CA.CLT_SITE_ID = CLIENT_SITE.CLT_SITE_ID)
     INNER JOIN USER_SECURITY ON (DEBT.CREATE_USER = USER_SECURITY.USER_ID)
     INNER JOIN ACCOUNT_STATUS ON (ACCOUNT.STATUS_CODE = ACCOUNT_STATUS.STATUS_CODE)
     INNER JOIN ZIP_CODE Z ON (COMPANY.ZIP_CODE_ID = Z.ZIP_CODE_ID)
     LEFT OUTER JOIN ZIP_CODE Z2 ON (CNTY.COURT_ZIP_CODE_ID = Z2.ZIP_CODE_ID)
WHERE
(CA.ACCT_ID = :ACCT_ID) A
ND
(CA.CASE_ID = :CASE_ID)
ORDER BY ACCOUNT.ACCT_ID ASC

As the cdsBatchPrintItem dataset is being processed it sets the following variable that is used in the code segment below:
iAppendCount := cdsBatchPrintItemNO_OF_COPIES_TO_PRINT.AsInteger - 1;

Then cdsPrintBatchItem passes the ACCT_ID and CASE_ID values to cdsMergeCase which pulls just one record.

Here is where my problem starts.  If iAppendCount is 0, there is no problem.  However if iAppendCount > 0, then I receive a "Key Violation" when the cdsTemp.Post line is executed.

Here is the relavent source code:

                                  //* MGT Merge the data to a temp dataset
                                  if not bcdsTempCloned then
                                    begin
                                      //* MGT Create a temporary cds to clone the data in cdsMergeCase
                                      cdsTemp := TClientDataSet.Create(nil);

                                      //* MGT Clone cdsMergeCase
                                      cdsTemp.CloneCursor(cdsMergeCase,FALSE,FALSE);

                                      //* 06.20.07 Must set to 0;
                                      cdsTemp.PacketRecords := 0;

                                      //* MGT Create a datasource and connect it to the dataset
                                      dtsTemp := TDataSource.Create(nil);
                                      dtsTemp.DataSet := cdsTemp;

                                      bcdsTempCloned := True;
                                    end
                                  else
                                    begin
                                      cdsTemp.Append;

                                      for I := 0 to cdsMergeCase.FieldCount -1 do
                                        begin
                                          sFieldName := cdsMergeCase.Fields[I].FieldName;
                                          vFieldValue := cdsMergeCase.Fields[I].AsVariant;

                                          cdsTemp.FieldByName(sFieldName).AsVariant := vFieldValue;
                                        end;

                                      cdsTemp.Post;
                                    end;

                                  //* 02.29.08 Append addtional records to the temp print table
                                  if iAppendCount > 0 then
                                    begin
                                      For B := 1 to iAppendCount do
                                        begin
                                          cdsTemp.Append;

                                          for I := 0 to cdsMergeCase.FieldCount -1 do
                                            begin
                                              sFieldName := cdsMergeCase.Fields[I].FieldName;
                                              vFieldValue := cdsMergeCase.Fields[I].AsVariant;

                                              cdsTemp.FieldByName(sFieldName).AsVariant := vFieldValue;
                                            end;

                                          cdsTemp.Post;   <<< Key Violation
                                        end
                                    end;

Now I understand that a Key Violation is usually caused by the TProvidedFlags being set to pfInKey on the key fields.  However, because cdsMergeCase (cloned to cdsTemp) is a dummy dataset that can contain any custom SQL and no persistent fields, I thought that none of the fields would have this flag set.  I was wrong as I found while debugging that these fields (AccountID, CaseID, ClientID and ClientSiteID) had the pfInUpdate, pfInWhere and pfInKey flags set, even though I did not set them.  Is this some 
new since Delphi 5 that it automatically determines this based on the custom SQL?

I also determine while debugging that cdsTemp.IndexFieldNames = '' 

Where do I go form here?  I need to be able to have duplicates of the same cdsMergeCase record in the cdsTemp dataset.

Anyone that is able to shed some like I would truly appreciate your help.

Thanks,
Mike

Vote for best question.
Score: 0  # Vote:  0
Date Posted: 13-Mar-2014, at 10:36 AM EST
From: Michael Tuttle