Skip to main content

I have a DAC MySOInfo defined as Child of SOOrder and another DAC MySODetail as Child of MySOInfo.

If a SOOrder is deleted in Screen SO301000, I would expect that the linked MySOInfo entries are deleted and MySODetail entries, too. In fact the first Children MySOInfo are deleted but the Children’s Children MySODetail are not deleted.

The DAC’s are defined like this:

  eSerializable]
PXCacheName("MySOInfo")]
public class MySOInfo : IBqlTable
{
#region RecordID
PXDBIdentity(IsKey = true)]
public virtual int? RecordId { get; set; }
public abstract class recordId : PX.Data.BQL.BqlInt.Field<recordId> { }
#endregion

#region OrderNbr
PXParent(typeof(SelectFrom<SOOrder>.Where<SOOrder.orderNbr.IsEqual<orderNbr>
.And<SOOrder.orderType.IsEqual<orderType>>>))]
PXDBString(15, IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Order Nbr")]
public virtual string OrderNbr { get; set; }
public abstract class orderNbr : PX.Data.BQL.BqlString.Field<orderNbr> { }
#endregion

#region OrderType
PXDBString(2, IsFixed = true, InputMask = "")]
PXUIField(DisplayName = "Order Type")]
public virtual string OrderType { get; set; }
public abstract class orderType : PX.Data.BQL.BqlString.Field<orderType> { }
#endregion
....
}


Serializable]
PXCacheName("MySODetail")]
public class MySODetail : IBqlTable
{
#region BaseRecordID
PXParent(typeof(SelectFrom<MySOInfo>.Where<MySOInfo.recordId.IsEqual<baseRecordID>>))]
PXDBInt(IsKey = true)]
public virtual int? BaseRecordID { get; set; }
public abstract class baseRecordID : PX.Data.BQL.BqlInt.Field<baseRecordID> { }
#endregion
...
}

What do I have to do to have the Children’s Children deleted as well.

Your are missing .FromCurrent in your PXParent attribute declarations. It should look like:

 [PXParent(typeof(SelectFrom<MySOInfo>.Where<MySOInfo.recordId.IsEqual<baseRecordID.FromCurrent>>))]

The same issue exists with your other DAC.

Note that I would strongly recommend adding OrderType before OrderNbr -- the SOOrder table has a composite primary key, and beside the risk of the same order nbr. being present in different order types, this will negatively affect performance since SQL will not be able to fully used the clustered index that exist.


Thank you for the very fast reply @Gabriel Michaud .

Adding .FromCurrent makes no difference.

 

Any more ideas?


Hi @mhaps ,

You just need to add the PXParent attribute and DBDefault for the Child DAC MySODetail …

Please find the example below..

 

eSerializable]
/PXCacheName("MySODetail")]
public class MySODetail : IBqlTable
{
#region BaseRecordID
/PXParent(typeof(Select<MySOInfo, Where<MySOInfo.recordId, Equal<Current<MySODetail.baseRecordID>>>>))]
PXDBInt(IsKey = true)]

rPXDBDefault(typeof(MySOInfo.recordId))]
public virtual int? BaseRecordID { get; set; }
public abstract class baseRecordID : PX.Data.BQL.BqlInt.Field<baseRecordID> { }
#endregion
...
}

 

Hope this helps!!


@mhaps  Below article might be help you…

https://asiablog.acumatica.com/2019/04/grids-master-detail-relationship.html


I created a Graph for the first level Child MySOInfo. If I delete MySOInfo entries from this graph, the MySODetail entries are deleted. So the both master/detail relationships seem to be ok.

It is just the Cascading delete that does not work.Only the direct Children are deleted, not the Children’s Children.


@mhaps,

Sorry, I’m bit confused….In your requirement do you have 3 DAC file? (you have given only 2 DAC files bro)

Parent DAC  → Parent Child DAC → Child’s Child DAC ?

When your deleting the Parent DAC, then you need to delete the “Parent Child DAC” records and “Child’s Child DAC” records right?

if yes, can you please provide the 3 DAC files here?  

 


Yes 3 DAC’s. The missing one is the native SOOrder.

SOOrder → MySOInfo → MySODetail

When an SOOrder is deleted in SO301000, MySOInfo and MySODetail should be deleted, too


@maps Can you please try with below code and verify..

 

>Serializable]
PXCacheName("MySOInfo")]
public class MySOInfo : IBqlTable
{
#region RecordID
PXDBIdentity(IsKey = true)]
public virtual int? RecordId { get; set; }
public abstract class recordId : PX.Data.BQL.BqlInt.Field<recordId> { }
#endregion

#region OrderNbr
PXDBString(15, IsUnicode = true, InputMask = "")]
///PXParent(typeof(SelectFrom<SOOrder>.Where<SOOrder.orderNbr.IsEqual<orderNbr>
//.And<SOOrder.orderType.IsEqual<orderType>>>))]

PXParent(typeof(Select<SOOrder, Where<SOOrder.orderType, Equal<Current<MySOInfo.orderType>>,
And<SOOrder.OrderNbr, Equal<Current<MySOInfo.OrderNbr>>>>>))]

PXDBDefault(typeof(SOOrder.orderNbr))]
PXUIField(DisplayName = "Order Nbr")]
public virtual string OrderNbr { get; set; }
public abstract class orderNbr : PX.Data.BQL.BqlString.Field<orderNbr> { }
#endregion

#region OrderType
PXDBString(2, IsFixed = true, InputMask = "")]
PXUIField(DisplayName = "Order Type")]
public virtual string OrderType { get; set; }
public abstract class orderType : PX.Data.BQL.BqlString.Field<orderType> { }
#endregion
....
}

Serializable]
PXCacheName("MySODetail")]
public class MySODetail : IBqlTable
{
#region BaseRecordID

PXDBInt(IsKey = true)]
PXParent(typeof(Select<MySOInfo, Where<MySOInfo.recordId, Equal<Current<MySODetail.baseRecordID>>>>))]
PXDBDefault(typeof(MySOInfo.recordId))]
public virtual int? BaseRecordID { get; set; }
public abstract class baseRecordID : PX.Data.BQL.BqlInt.Field<baseRecordID> { }
#endregion
...
}


Finally I found it out, or at least a workaround.

I make use of MySOInfo in an extension of SOOrderEntity, where the delete action is executed. MySODetail is not used in this graph. There is another graph for MySOInfo and MySODetail.

Now I’ve added an unsed view of MySODetail in the SOOrderEntity extension graph and violá MySODetail entries are deleted.

 

I don’t like this unused view but it seems that the master-detail relation in the DAC classes are not sufficient for cascading delete.


Yes… that is correct!! 

To work with cascading deletion we need to have a views declaration in that particular graph. Even we are using or not we need to create dummy views to work with cascading deletion….


Reply