Solved

Cascading Delete [PXParent] does not work


Badge

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:

  [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
[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.

icon

Best answer by Naveen B 11 June 2021, 14:47

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….

View original

10 replies

Userlevel 6
Badge +7

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.

Badge

Thank you for the very fast reply @Gabriel Michaud .

Adding .FromCurrent makes no difference.

 

Any more ideas?

Userlevel 6
Badge +4

Hi @mhaps ,

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

Please find the example below..

 

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

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

 

Hope this helps!!

Userlevel 6
Badge +4

@mhaps  Below article might be help you…

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

Badge

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.

Userlevel 6
Badge +4

@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?  

 

Badge

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

Userlevel 6
Badge +4

@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
...
}

Badge

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.

Userlevel 6
Badge +4

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


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2020  Acumatica, Inc. All rights reserved