AnyDAC
ContentsIndexHome
PreviousUpNext
Editing Questions

The list of questions and answers related to data editing.

Group
Links
QE1: What means "[AnyDAC][DApt]-400. Update command updated [0] instead of [1] record" ?

A: This error often happens when AnyDAC includes some float / double / single / date / datetime / time or some other table fields, which are the subject to the precision lost, into WHERE phrase. Then at the parameter assignments the precision lost may happen. As result of that the WHERE phrase returns no records. 

AnyDAC may include such fields into WHERE depending on UpdateOptions.UpdateMode. Sometimes you can see this error with upWhereKeyOnly. Although you have specified upWhereKeyOnly, AnyDAC still may use upWhereAll. Which is fallback, when there is no PK fields defined. No PK fields may be defined when:

  • fiMeta is excluded from FetchOptions.Items;
  • or table in SQL does not have primary key defined;
  • or UpdateOptions.KeyFields is empty;
  • or none of TField's has pfInKey in ProviderFlags.

Other reason with some DBMS (SQL Server, PostgreSQL) is that the table has a trigger, which modifies the data. With SQL Server put SET NOCOUNT ON at trigger beginning. With PostgreSQL set UpdateOptions.CountUpdatedRecords to False. 

 

QE2: When it is necessary to use TADUpdateSQL?

A: AnyDAC generates updating SQL commands automatically, when the original SQL command is a simple SELECT or a SELECT with JOIN, where is a single table preserving the primary key fields. So, the TADUpdateSQL usage is optional. TADUpdateSQL is required when:

  • The original SQL command is not a SELECT command. Eg, stored procedure returning result sets or what else.
  • The original SELECT command is not preserving primary key. Eg, join few tables, has DISTINCT or GROUP BY clauses, etc.
  • An application needs non-standard update SQL command. Eg, application is posting updates using stored procedure calls.

 

QE3: Is it possible to use Macros inside SQLs in ADUpdateSQL?

A: Use the following code: 

 

ADUpdateSQL1.Commands[arInsert].MacroByName('MacroName').Value := 'value';

 

QE4: Why in CachedUpdates mode calling ApplyUpdates more than once tries to post inserted records again ?

A: After calling ApplyUpdate, you should call CommitUpdates. After this call all changes will be deleted from internal cache. 

 

QE5: How do not refresh a detail TADQuery after a master TADQuery is scrolled or posted ?

A: Two ways:

  • Implement master-detail linkage on your own. This will require to add TDataSource.OnDataChange event handler. I will call this "standard" way.
  • To use Centralized Cached Updates.

 

QE6: How to remove few dataset records, without removing them from DB.

A: You can work directly with internal dataset data storage. It is accessible through TADDataSet.Table property. For example, to delete row with index 3 do the following: 

 

ADQuery1.Table.Rows[3].Free;
ADQuery1.UpdateCursorPos;
ADQuery1.Resync([]);

 

For example, to delete the current record do the following: 

 

ADQuery1.UpdateCursorPos;
ADQuery1.GetRow.Free;
ADQuery1.UpdateCursorPos;
ADQuery1.Resync([]);

 

And finally you can use CachedUpdates mode. Set a dataset to the cached updates mode. Then delete a record and call CommitUpdates. 

 

QE7: ATable.UpdateToDataset(BTable , 'mykey', [mtufEdit, mtufAppend]) – how can I do this with AnyDAC?

A: Use the TADDataSet.CopyDataSet method with the following options:

  • [coAppend] - append all records from ASource (as it was);
  • [coEdit] - edit only records with existing key values;
  • [coAppend, coEdit] - edit records with existing keys and append records with non-existent keys.

 

QE8: How to assign value to a ftGUID field ?

A: Use the following code: 

 

(AMemTable.FieldByName('Field1') as TGUIDField).AsGuid := aGUID;

 

QE9: How to specify a default value for a dataset field ?

A: Assign an expression to the TField.DefaultExpression property. 

 

QE10: Whether property TField.DefaultExpression is being supported in the analogous way as TField.CustomConstraint, and the effect of the expression is being written, as the default value for a field?

Yes, if a field is a normal resultset field. If a field is fkInternalCalc one, then the result of the DefaultExpression will be used as a field value. And it will be updated like any other calculated fields. 

 

QE11: E.g. such an expression: {fn DAYOFMONTH({fn CURDATE()})} will be correct?

A: No, you are using AnyDAC escape functions. They are supported only in the SQL commands, not in expressions. In expressions, like constraints and default value expressions, you should use functions and syntax, supported by AnyDAC expression evaluator: 

 

DAYOFMONTH(CURDATE())

 

Also, to use such functions, you should include uADStanExprFuncs unit into your application. 

 

QE12: How to specify default value for a dataset Boolean field ?

A: To specify a default value for a dataset field, assign required expression to the TField.DefaultValue property. 

To assign default value to a boolean field, you can use one of the following strings - F, FA, FAL, FALS, FALSE as False names. And similar for True. 

 

QE13: Assigning TField.CustomConstraint does not work. What is wrong ?

Q: Appending constraint via: 

 

ADQuery.FieldByName('FIELD_NAME').CustomConstraint := 'FIELD_NAME > 1';
ADQuery.UpdateConstraints;
ADQuery.Table.Constraints.Check(ADQuery.GetRow(), rsModified, ctAtEditEnd);

 

It's not working - exception is not raised... 

A: That is OK (explanation will be later). 

 

Q: But: 

 

ADQuery.Constraints.Add.CustomConstraint := 'FIELD_NAME > 1';
ADQuery.UpdateConstraints;
ADQuery.Table.Constraints.Check(ADQuery.GetRow(), rsModified, ctAtEditEnd);

 

It's working! Why? 

A: Also OK. 

 

Q: What exactly mean ctAtEditEnd and ctAtColumnChange? 

A: These enums are specifying the event, when AnyDAC should check constraints:

  • ctAtEditEnd - the Post is called
  • ctAtColumnChange - a field value is modified

Now explanation: 

 

ADQuery.FieldByName('FIELD_NAME').CustomConstraint := 'FIELD_NAME > 1';

 

This is adding a field-level constraint. They are checked at ctAtColumnChange event only. 

 

ADQuery.Constraints.Add.CustomConstraint := 'FIELD_NAME > 1';

 

This is adding a record-level constraint. They are checked at ctAtEditEnd event only.

What do you think about this topic? Send feedback!