public void insert() { if (0 != this.TableExtensionParent) { // only insert if the FK is valid super(); } }update
public void update() { if (0 != this.TableExtensionParent) { // only update if the FK is valid super(); } }find
public static TableExtensionChild find( recId _recId, boolean _forUpdate = false, ConcurrencyModel _concurrencyModel = ConcurrencyModel::Auto) { TableExtensionChild tableExtensionChild; tableExtensionChild.selectForUpdate(_forUpdate); if (_forUpdate && _concurrencyModel != ConcurrencyModel::Auto) { tableExtensionChild.concurrencyModel(_concurrencyModel); } select firstonly tableExtensionChild where tableExtensionChild.RecId == _recId; return tableExtensionChild; }findByParent
public static TableExtensionChild findByTableExtensionParent(RecId _tableExtensionParentRecId, boolean _forUpdate = false) { TableExtensionChild tableExtensionChild; tableExtensionChild.selectForUpdate(_forUpdate); if (_tableExtensionParentRecId != 0) { select firstonly * from tableExtensionChild where tableExtensionChild.TableExtensionParent == _tableExtensionParentRecId; } return tableExtensionChild; }
public TableExtensionChild tableExtensionChild() { return this.SysExtensionSerializerMap::getExTensiontable(tableNum(TableExtensionChild)); }
public void packTableExtensionChild(TableExtensionChild _tableExtensionChild) { _tableExtensionChild.TableExtensionParent = this.RecId; this.SysExtensionSerializerMap::packExtensionTable(_tableExtensionChild); }
public static QueryBuildDataSource addDataSource(QueryBuildDataSource _parentDataSource, TableId _tableId, JoinMode _joinMode = JoinMode::InnerJoin) { QueryBuildDataSource qbds; if (null == _parentDataSource || tableNum(TableExtensionParent) != _parentDataSource.table() || tableNum(TableExtensionChild) != _tableId) { throw error(error::wrongUseOfFunction(funcName())); } switch (_tableId) { case tableNum(TableExtensionChild): qbds = _parentDataSource.addDataSource(_tableId); qbds.addLink(fieldNum(TableExtensionParent, RecId), fieldNum(TableExtensionChild, TableExtensionParent)); qbds.fetchMode(QueryFetchMode::One2One); qbds.joinMode(_joinMode); break; } return qbds; }
public void insert() { super(); this.SysExtensionSerializerMap::postInsert(); }
public void update() { super(); this.SysExtensionSerializerMap::postUpdate(); }
public void write() { super(); TableExtensionChild.SysExtensionSerializerExtensionMap::insertAfterBaseTable(TableExtensionParent); }write method of child table triggers first and as a result child record will not be saved as it's insert and update methods does not allow it without correct foreign key.
If you found value in what I share, I've set up a Buy Me a Coffee page as a way to show your support.
Buy Me a CoffeeHello
Thanks for the great article.
I would like to add that if the parent table's primary key is not RecId-based, but the table has CreateRecIdIndex property set to Yes, then the relation on step #1 should be created based on "Single field AlternateKey based"; otherwise the new feld will potentially have wrong type, and it will not be possible to use it in the SysExtensionSerializerExtensionMap map.
Also, people have to remember to add a DeleteAction to the parent table.
this approach does not work if you are exposing these 2 parent and child tables through an AIF document service.
1. Child table record gets created as part of parent table record
2. Then AIF document service framework tries to create the Child table record again and throws an error something on the lines "Record already exists".
DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics 365 FO.
Authors are allowed to set their own "buy me a coffee" link.
Join us.