More than one UBAQ in a Dashboard?

What is the critical piece of code that creates the EpiDataView binding? I am trying to run the custom action through the DynData. Clearly I am in over my head, and I just need some training on the crazy layers involved. :stuck_out_tongue:

private DataTable Ourresults;

	private void epiBtnUpdateOur_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		
		Ourresults = new DataTable();		
		DataSet OurData = ddmyOpenOrders.RunCustomAction("GE_ThisWeekUpdate_OurUnmatched", "ProcessCommands", Ourresults.DataSet, true);
	}

I don’t want to get too much into the specific code I sent you because on a public forum it’s not going to be relevant to most people who could stumble across this thread. But in general terms …

The core elements you need around to make the Dynamic Query object work are the adapter itself, the results DataSet, the execution DataSet and the results DataTable, together with the Transaction object. So the class that makes the code reusable contains those things and re-uses them.

When you call Execute, the results DataSet is populated. QueryResults.Tables[“Results”] is the DataTable that holds the data you see in a BAQ. If you create an EpiDataView (or have one already in the Transaction DataViews collection) then setting dataView = QueryResults.Tables[“Results”].DefaultView means that EpiDataView then has your BAQ data in it.

I’d be handling more of this within the class myself, I think, but as I say I’m not sure getting too specific here is a good idea.

Here is my attempt to create what Daryl is talking about. It doesn’t work quite yet, but I feel like I am close. I created a function to load my BAQs into the correct UltraGrids. The code comlies correctly, but errors when I open the form.

	public void LoadMyBAQ(string myBAQ, EpiUltraGrid myGrid)
	{
	Ice.BO.DynamicQueryDataSet dsQuery;
	Ice.BO.QueryExecutionDataSet dsBAQ;
	//adapter
		DynamicQueryAdapter yourbaq = new DynamicQueryAdapter(this.oTrans);
		DynamicQueryAdapter termsadp = new DynamicQueryAdapter(this.oTrans);
	//results ds
		DataTable results;
		yourbaq.BOConnect();
		string baqname = myBAQ;
		dsQuery = termsadp.DynamicQueryData;
	//execution ds
		dsBAQ = yourbaq.GetQueryExecutionParameters(dsQuery);
		yourbaq.Execute(dsQuery, dsBAQ);
	//results dt
		if (yourbaq.QueryResults != null && yourbaq.QueryResults.Tables.Count > 0)
		{
			results = yourbaq.QueryResults.Tables["Results"];
		}
		else
		{
			results = new DataTable();
		}
	//set results to ultragrid
	myGrid.DataSource = yourbaq.QueryResults.Tables["Results"].DefaultView;
	}

I call this inside here:

    public void InitializeCustomCode()
    	{

    	LoadMyBAQ("x_ThisWeeksUpdate_OpenOrders", epiUltraGridC1);
    	LoadMyBAQ("x_ThisWeekUpdate_OurUnmatched", epiUltraGridC2);


I debugged in VS and found that the error was in the execute line, perhaps because the datasets were not setup correctly.

Application Error

Exception caught in: mscorlib

Error Detail

Message: Exception has been thrown by the target of an invocation.
Inner Exception Message: Can’t find query definition in passed dataset
Program: CommonLanguageRuntimeLibrary
Method: InvokeMethod

Client Stack Trace

at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at Ice.Lib.Customization.CustomScriptMethodInvoker.InvokeScriptMethod(MethodInfo scriptMethod, Object parameters)
at Ice.Lib.Customization.CustomScriptMethodInvoker.InvokeInitializeCustomCodeIfExists()
at Ice.Lib.Customization.CustomScriptManager.TryActionShowExceptionBoxOrLogVerificationErrorIfException(Action action, String exceptionBoxTitle)

Inner Exception

Can’t find query definition in passed dataset

at Epicor.ServiceModel.Channels.ImplBase`1.ShouldRethrowNonRetryableException(Exception ex, DataSet dataSets)
at Ice.Proxy.BO.DynamicQueryImpl.GetQueryExecutionParameters(DynamicQueryDataSet queryDS)
at Ice.Adapters.DynamicQueryAdapter.GetQueryExecutionParameters(DynamicQueryDataSet ds)
at Script.LoadMyBAQ(String myBAQ, EpiUltraGrid myGrid)
at Script.InitializeCustomCode()

I appreciate any help you can give.
Thanks!
Nate

As per the other thread, my error has led to you using two adapters when you only need one, so in your code here each adapter is only getting half what it should to be able to work.

Use only “yourbaq” and put it in place of where you’ve used “termsadp” and you should be most of the way there.

I tried that first actually. I was still getting the same error.

Debugging in Visual Studio shows that these lines are the culprit:

    dsBAQ = yourbaq.GetQueryExecutionParameters(dsQuery);
    yourbaq.Execute(dsQuery, dsBAQ);

So I swapped out this method for .GetQueryExecutionParametersByID(myBAQ);

Here is my cleaned up code that still gives the same error.

    public void LoadMyBAQ(string myBAQ, EpiUltraGrid myGrid)
    	{
    		Ice.BO.DynamicQueryDataSet dsQuery;
    		Ice.BO.QueryExecutionDataSet dsBAQ;
    		DataTable results;	
    		
    		//adapter
    			DynamicQueryAdapter yourbaq = new DynamicQueryAdapter(this.oTrans);
    			yourbaq.BOConnect();
    		//results ds
    			dsQuery = yourbaq.DynamicQueryData;
    		//execution ds
    			dsBAQ = yourbaq.GetQueryExecutionParametersByID(myBAQ);
    			yourbaq.Execute(dsQuery, dsBAQ);
    		//results dt
    			if (yourbaq.QueryResults != null && yourbaq.QueryResults.Tables.Count > 0)
    			{
    				results = yourbaq.QueryResults.Tables["Results"];
    			}
    			else
    			{
    				results = new DataTable();
    			}
    		//set results to ultragrid
    		myGrid.DataSource = yourbaq.QueryResults.Tables["Results"].DefaultView;
    		
    		/*EpiDataView edv = (EpiDataView)oTrans.EpiDataViews[myBAQ];
    		if (!(edv != null))
    		{
    			edv = new EpiDataView();
    			oTrans.Add(myBAQ, edv);
    		}*/
    	}

I am confused by the use of EpiDataView, and the EpiUltraGrid. If I understand correctly EpiDataView is like a dataset in the background that can be used as a datasource for controls like an UltraGrid. Is that right?

What does that bit of code that I commented out at the bottom do?

Is there something obvious that I am missing with the Execute method?
Thanks you so much!!!
Nate

I have reviewed a lot of related threads, and found some simpler code to try. I have tried dozens of iterations and always come back to the same exact error. Here is my idealized, simplified code. It still throws the error. I feel like I am missing something critical.

	private void LoadMyBAQ(string myBAQ, EpiUltraGrid myGrid)
	{
		DynamicQueryAdapter dqa = new DynamicQueryAdapter(oTrans);
		QueryExecutionDataSet qeds = dqa.GetQueryExecutionParametersByID(myBAQ);
		Ice.BO.DynamicQueryDataSet ds = dqa.DynamicQueryData;		
		dqa.Execute(ds,qeds);
		myGrid.DataSource = dqa.QueryResults;
	}

Application Error

Exception caught in: mscorlib

Error Detail

Message: Exception has been thrown by the target of an invocation.
Inner Exception Message: Object reference not set to an instance of an object.
Program: CommonLanguageRuntimeLibrary
Method: InvokeMethod

Client Stack Trace

at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at Ice.Lib.Customization.CustomScriptMethodInvoker.InvokeScriptMethod(MethodInfo scriptMethod, Object parameters)
at Ice.Lib.Customization.CustomScriptMethodInvoker.InvokeInitializeCustomCodeIfExists()
at Ice.Lib.Customization.CustomScriptManager.TryActionShowExceptionBoxOrLogVerificationErrorIfException(Action action, String exceptionBoxTitle)

Inner Exception

Object reference not set to an instance of an object.

at Ice.Adapters.DynamicQueryAdapter.GetQueryExecutionParametersByID(String pcQueryId)
at Script.LoadMyBAQ(String myBAQ, EpiUltraGrid myGrid)
at Script.InitializeCustomCode()

I got the grids to load the data like I want. But I couldn’t get it working with the Execute method. I had to use the ExecuteByID. I am afraid this will come back to bite me once I try to utilize the updateable features of the UBAQs. But this code is so much simpler!

	private void LoadMyBAQ(string myBAQ, EpiUltraGrid myGrid)
	{
		DynamicQueryAdapter dqa = new DynamicQueryAdapter(oTrans);
		dqa.BOConnect();
		dqa.ExecuteByID(myBAQ);		
		myGrid.DataSource = dqa.QueryResults;
	}

Now that I have this in place I am going to start working on running my custom actions through some buttons on the form.

Thanks!!!
Nate

Please let me know if I am getting too far off the main topic here.

I am trying to utilize the custom action in my UBAQ. Building on the successful code I last posted, this button code should:

  1. Look at the checkboxes the user ticked on the UltraGrid. (This is really done in the BPM, but I think I may need to “update” the query after the user checks those boxes so that they are actually checked when the BPM runs, right?)
  2. Run the custom action “ProcessCommands”.
  3. Reload the UltraGrid with the updated query results.

Here is my button code:

    	private void epiBtnUpdateOur_Click(object sender, System.EventArgs args)
    	{
    		// ** Place Event Handling Code Here **
    		DynamicQueryAdapter dqa = new DynamicQueryAdapter(oTrans);
    		DataTable results;		
    		DataTable dtresults;
    		results = new DataTable(); 	   
    		dtresults = new DataTable();
    		dqa.BOConnect();
    		dqa.ExecuteByID("x_ThisWeekUpdate_OurUnmatched");
    		dqa.Update("x_ThisWeekUpdate_OurUnmatched", results.DataSet);
    		dqa.RunCustomAction("x_ThisWeekUpdate_OurUnmatched", "ProcessCommands", dtresults.DataSet, true);
    		LoadMyBAQ("x_ThisWeekUpdate_OurUnmatched", epiUltraGridC2);
    	}

This is the error I am getting when I click the button.

Application Error

Exception caught in: Epicor.ServiceModel

Error Detail

Message: There is no BPM customization attached to Update method of ‘x_ThisWeekUpdate_OurUnmatched’ updatable query in ‘VTAERO’ company or BPM system is not enabled.
Please check presence of BPM customization and/or ask administrator for assistance.
Program: Epicor.ServiceModel.dll
Method: ShouldRethrowNonRetryableException

Client Stack Trace

at Epicor.ServiceModel.Channels.ImplBase1.ShouldRethrowNonRetryableException(Exception ex, DataSet[] dataSets) at Ice.Proxy.BO.DynamicQueryImpl.UpdateByID(String queryID, DataSet queryResultDataset) at Ice.Adapters.DynamicQueryAdapter.<>c__DisplayClass28_0.<Update>b__0(DataSet datasetToSend) at Ice.Adapters.DynamicQueryAdapter.ProcessUbaqMethod(String methodName, DataSet updatedDS, Func2 methodExecutor, Boolean refreshQueryResultsDataset)
at Ice.Adapters.DynamicQueryAdapter.Update(String queryID, DataSet updatedDS)
at Script.epiBtnUpdateOur_Click(Object sender, EventArgs args)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at Infragistics.Win.Misc.UltraButtonBase.OnClick(EventArgs e)
at Ice.Lib.Framework.EpiButton.OnClick(EventArgs e)
at Infragistics.Win.Misc.UltraButton.OnMouseUp(MouseEventArgs e)
at Ice.Lib.Framework.EpiButton.OnMouseUp(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

EDIT: I guess this success was a fluke. After some tweaking I came back and reused this code that once worked. Now I still get the error from above.

There is no BPM customization attached to Update method of ‘x_ThisWeekUpdate_OurUnmatched’ updatable query in ‘VTAERO’ company or BPM system is not enabled.

END EDIT

I got the custom action to work! Sort of… The action runs, and completes as if no checkboxes have been selected. The problem seems to be that the custom actions don’t see the checkboxes I have clicked. I think there is a problem in the Update part of the code.

I know the BPMs work well on their own.

	private void epiBtnUpdateOur_Click(object sender, System.EventArgs args)
	{
		// ** Place Event Handling Code Here **
		DynamicQueryAdapter dqa = new DynamicQueryAdapter(oTrans);
		DataTable results;		
		results = new DataTable(); 	   
		dqa.BOConnect();
		dqa.Update("x_ThisWeekUpdate_OurUnmatched", results.DataSet);
		dqa.RunCustomAction("x_ThisWeekUpdate_OurUnmatched", "ProcessCommands", results.DataSet, true);
		LoadMyBAQ("x_ThisWeekUpdate_OurUnmatched", epiUltraGridC2);
	}

I’ll try to look through some of this when I have a minute, but two things are worth mentioning straight away:

  • One of my team regularly gets that “No BPM attached” error with uBAQs, and I think it’s a bug. You can normally fix it by going to your uBAQ, making it non-updatable and saving, then making it updatable and saving again. The code seems to stay intact through doing that and somehow re-registers it with the main system.
  • As I said before, we don’t use Custom Actions (we tend to put everything we need into Update), but I think you need to pass in the dataset that contains your changes unless those changes are irrevelevant.

That didn’t work for me unfortunately. Now it seems like all of my custom actions are gone from both UBAQs. I don’t know how that could happen, but there are no custom actions in either BAQ. Now I have to figure out how to rebuild them. :frowning:

If you uncheck updateable, and save, your BPM’s go bye bye.

Mine don’t …?

We have this problem (one of my team regularly). Yes, the BPMs disappear when you un-check and save, but they come back when you check that box and save again. It’s often the only we have of getting the system to acknowledge they exist.

Maybe it’s just the custom actions then. I’ve had them not come back. :cry:

I had the code backed up though, so it wasn’t a huge deal.

I don’t suppose there are any magic tricks to bring them back?
In all of my dozens of backup versions I neglected to get the version that worked. Backup, backup, and then backup again! Whoops! :stuck_out_tongue_closed_eyes:

Not that I know of. I had it pasted into notepad++ so I could see the code as I was in another one since I had 3 different baq’s all with their own custom actions that relied on the previous one. I got lucky I did that because when I was trying to test the BAQ without it being updateable I lost it.

Now I make sure I set up the custom action and call it by that rather than calling in on get rows, since if you do that, you can’t turn it of. lol

My N++ is full of snippets and samples. I should be able to piece it back together.

What do you mean by the last part? Setup custom action and call it? Rather than what?

I had the BPM on post processing for get list. I wanted everything that came back to be acted on. Problem is, every time you run the BAQ the BPM fires. So if I put it on custom action, I can get my list first then activate the customer action if I want. it makes it so you have to code am extra step but it’s better.

For those looking to for more info, head over to my related post: