Solved

Can I access a Data Record Cache and Graph without creating a new instance of the Graph?

  • 10 May 2024
  • 8 replies
  • 104 views

Userlevel 7
Badge +9

Hello all,

 

I have a scenario that I need to override a method which is used inside a Transaction Scope in the loop. Assume the method I am going to override is 

public virtual GLTran TheMethod(Batch batch)
{
//Do stuff
return tran;
}

The way the method is called is 

public virtual void TheReleaseDoc(JournalEntry je)
{
// Some loops and stuff here

foreach (Something)
{
// Do more stuff
GLTran tran = TheMethod(je.BatchModule.Current);
je.GLTranModuleBatNbr.Insert(tran);
}

// More loops and stuff here
}

I know I can initiate a new graph instance or use EntityHelper and then from the created graph instance access the viewes or methods BUT what I need is to access the same instance of the graph “je” from “TheMethod” to insert a copy of the “je.BatchModule.Current” and “je.GLTranModuleBatNbr.Insert(tran)” from inside “TheMethod”.

Is it possible to access a data record current instance of Cache and Graph? If yes, how can I do that?

icon

Best answer by NicholasBova52 11 June 2024, 15:54

View original

8 replies

Userlevel 7
Badge +9

Hello all,

I am circulating this thread to the top so hopefully someone has some idea how to make this work.

Userlevel 6
Badge +3

Hi @aaghaei,

Did you try to add JournalEntry je reference to a private global variable in your override of ReleaseDoc, and access it from TheMethod?

 

Userlevel 7
Badge +9

Hi @Zoltan Febert Thank you for the reply. I couldn’t quite underestand your comment but if this what you mean

public class MyCurrentInstances
{
public static JournalEntry je { get; set;}
}

public delegate void ReleaseDocProcDelegate(JournalEntry je, PRPayment doc);

[PXOverride]
public virtual void ReleaseDocProc(JournalEntry je, PRPayment doc, ReleaseDocProcDelegate baseMethod)
{
HCLCurrentInstances.je = je;
baseMethod?.Invoke(HCLCurrentInstances.je, doc);
}

then do this

MyCurrentInstances.je.Caches[typeof(GLTran)].Insert(tran);

yes this is how currently I amgoing around it but what I am hoping is from “tran” I get access to its Cache, View and Graph. The code gets a little bit messy and I am not fond of messy codes. Not sure if I could explain what I mean and if it possible or not.

Userlevel 4
Badge +1

@aaghaei 

 but what I am hoping is from “tran” I get access to its Cache, View and Graph.

If I understand what you’re asking here, is if you can determine from the “tran” DAC object which cache, view, and graph the object was created from. Are you trying to avoid inserting duplicate transactions into the cache if they already exist? If so, you can look through the “Inserted” and “Updated” collection properties on the cache, using the key fields to see to if that specific transaction exists.

Base.Caches[typeof(GLTran)].Inserted.ToArray<GLTran>().Where(t => t.BatchNbr == tran.BatchNbr && t.LineNbr == tran.LineNbr && t.Module == tran.Module);
Base.Caches[typeof(GLTran)].Updated.ToArray<GLTran>().Where(t => t.BatchNbr == tran.BatchNbr && t.LineNbr == tran.LineNbr && t.Module == tran.Module);

Otherwise, if you’re worried about the transaction being create/modified from one graph instance and used in another, you will need to perform this check in each graph object that’s currently loaded to make sure that’s not the case. In general, as long as you are creating and modifying transaction records from the same graph instance, this should not be an issue.

Userlevel 7
Badge +9

Hi @NicholasBova52 

Thank you for the reply. If the method I am overriding was in the graph I could access the graph and cache within the graph easily as you are correctly pointing out. However, the method I am overriding is in a class that is not a graph and that is why I don't know how to access the graph that using the class.

All is passed to the method in this class which is not a graph is “tran”.

Userlevel 4
Badge +1

@aaghaei In that case, if you just need access to the parent graph inside TheMethod, then @Zoltan Febert‘s approach should work.

 

If you want a cleaner approach to this, I suggest using a FlaggedModeScope, which is a disposable class defined in PX.Objects.Common.Scopes. You can define an inherited class of FlaggedModeScopeBase that accepts the JournalEntry as a parameter. Then you can wrap the body of the override of ReleaseDocProc inside a using that creates an instance of the inherited class containing the reference to the JournalEntry object.

 

Example:

using PX.Objects.Common.Scopes;

public class JournalEntryFlaggedModeScope : FlaggedModeScopeBase<JournalEntryFlaggedModeScope, JournalEntry>
{
public JournalEntryFlaggedModeScope(JournalEntry parameters) : base(parameters) { }
}

public class CDPRDocumentProcessExt : PXGraphExtension<PRReleaseProcess>
{
public static bool IsActive() => true;

public delegate void ReleaseDocProcDelegate(JournalEntry je, PRPayment doc);
[PXOverride]
public virtual void ReleaseDocProc(JournalEntry je, PRPayment doc, ReleaseDocProcDelegate baseMethod)
{
using (new JournalEntryFlaggedModeScope(je))
{
baseMethod?.Invoke(je, doc);
}
}

public delegate void TheMethodDelegate();
[PXOverride]
public virtual void TheMethod(TheMethodDelegate baseMethod)
{
if (JournalEntryFlaggedModeScope.IsActive)
{
var je = JournalEntryFlaggedModeScope.Parameters;
// Custom logic here, or after the invoke of the base method depending on business use case
}

baseMethod?.Invoke();
}
}

 

The benefit of this approach is that the life-cycle of the FlaggedModeScope object can be handled by the using block. Then, in your override of TheMethod, you can check whether the scope is active and then perform your custom functionality there. You don’t have to check whether or not the JournalEntry reference exists, because if the scope is active, then the parameter will supply the JournalEntry object. If the scope is not active, because TheMethod is being used by another part of the application, then the custom logic is ignored and you don’t have to worry about breaking existing functionality.

Userlevel 6
Badge +3

Thank you, @NicholasBova52 , for this insider info. It was incredibly useful. We need more answers like this in our community. Just three days after your response, I was able to use this approach in a customization project.

Userlevel 7
Badge +9

@NicholasBova52 what @Zoltan Febert pointed out is absolutely right. This is really what we need not unlike some comments that simply a person copies their comments “reach out to your VAR …” from one post to another and basically has NO value.

Much appreciated your time and valuable response. Sorry I did mark this post as completed with 2 days delay but I was meaning to write something nice that Zoltan did. Thank you both.

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 — 2024  Acumatica, Inc. All rights reserved