Basically our customers are very predictable, and order the same products and very similar volumes each week. Even to the point of taking delivery on the same day. This allows us to spot possible order entry errors, and correct them.
I want to populate the grid with rows containing a name, then description of the issue:
I will have to write the C# code to work out the answers to those examples that I posted. My actual query for today is how to populate the non-bound grid. Do I go after the rows in EpiUltraGrid, do I bind it to an EpiDataView, or a DataTable? I want to know best practice.
I have also considered a BAQView, but I want to be flexible in the checks that I do - I couldn’t see a way to bind the results from 5 or 10 different BAQs into the same grid so have ruled this out in my mind at present.
We do this kind of thing quite a lot, and while I can’t answer for best practice, I can tell you what works for us.
Create BAQ(s) for the data you want, limiting it as far as you can by means of parameters.
DynamicQuery business object, using “Execute” rather than “ExecuteByID” (it’s faster for some reason), passing any parameters.
Create a blank EpiDataView with the same name as the BAQ you’re using, and make its dataView the defaultView of the returned Results table.
Either use the EpiBinding of the grid and bind to the EpiDataView (if you don’t want to do any special formatting or anything on the grid) or bind the DataSource of the grid directly to Results table itself. Both ways work equally well and preserve key functionality like keeping bindings in sync and allowing users to “Open with”.
We’ve packaged a lot of this functionality up for re-use within the company including a lot of other nice-to-haves, and it’s been working well for us so far.
But in this case my queries are looking at totally unrelated tables. I want to look at UD01 for Route Info, OrderRel for Delivery Data, OrderHed for average order values, OrderHed for multiple orders within given period.
Would I therefore going down the BAQ route need to have 1 grid per BAQ? Everything that I know tells me I would need multiple grids, which isn’t going to look great!
To be honest, I do usually find a way of packaging up that kind of data into one BAQ. Via joins, unions, or whatever works with reasonable performance.
But having said that, you can do the steps I outlined without binding to a grid at all. If you then close and re-open the form with the customization active then you’ll find your data in the list of BAQs and you can bind the relevant fields to any type of control.
I’ll be interested to see what anybody else recommends, mind you.
@markdamen I’d say it comes down to preference. What makes the most sense for displaying your data? If you want to go with multiple grids, you can set them up as pub/sub if one drives the other.
They are all unrelated, so publish/subcribe wouldn’t make sense. I really would like to just create rows in 1 grid, so my question is:
How are DataTables / EpiDataView / EpiUltraGrids related? You’ll notice @Chris_Conn that it’s a similar query to my one the other day . I’m still not properly understanding which one I should interact with. I know that an EpiUltraGrid can be bound, and that binding would be to an EpiDataView. So should I create an EpiDataView, bind my EpiUltraGrid to said EDV and then interact with the EDV? Or does the EDV itself not hold any data, and infact is just a “view” on the data held within a DataTable?
Jumping in again, there are two ways of binding a grid. You can use EpiBinding, which has to be to an EpiDataView, or in code with DataSource, which is to a DataTable. The EpiBinding is Epicor’s addition to Infragistics’ standard code for UltraGrid, but the UltraGrid itself is still standard and you can use any of Infragistics’ normal methods and properties which are much better documented than Epicor’s.
So, if you’re insistent on a grid, and don’t want to package up into a BAQ, the sensible course is to create a DataTable, get your data by what means you like (I’d still use DynamicQuery because for me it’s a known quantity, but there are other ways), and put the data into rows in the DataTable, then use it as the source for the grid.
So the EDV is just a fancy dataview with the EpiMagic, but that’s where the beauty lies. Like @dhewi mentioned, you can bind a grid right to a DataTable. By using an EDV you get all the extra epicor features:
EpiBinding (especially to other controls for manipulation)
OpenWith
Easy Pub/Sub
Create BAQs for each of the individual checks that I want to perform
Learn how to pass a Parameter from C# code to the BAQ
Insert the resulting row from the BAQ (will only ever be 1) into a DataTable
Bind the EpiUltraGrid to the DataTable
Does the EUG update when changes are made to the underlying table, or do you have to call an update?
If you want code for passing the parameters to DynamicQuery I can give you that.
I do have the other bits working in different places too, but they aren’t quite as accessible to pass on, but if you get stuck I can look.
Re the last question, no, there’s no automatic update. What we usually do is call GetData again on the DynamicQuery when the user changes something relevant or clicks refresh.
Re @Chris_Conn’s comment on the EpiMagic, the really nice thing is that you can have it both ways. If you create an EpiDataView and make its dataView the DefaultView of your DataTable then you get the magic, whether or not you choose to use EpiBinding on the grid itself. But from your statement of your initial aims, I don’t think any of the magic is going to be of interest for this particular thing.
If you’re willing to share the code for calling BAQs with parameters that would be awesome. It’s possible they’ve been shared before on the forum, but to have it on this thread is great.
With your help I’ve been able to mock up using code what I want to achieve:
I have a meeting now, but excited to get back to this and hook up the dynamic elements to check based on the currently loaded order. Final challenge is to wire it up so that it works automatically. That raises the question about when the order is “finished”. If I fire it after 1 line, and the customer normally takes 5 lines that it’s immediately going to fail on the Order Value check. I might need to retrain users to click ReadyToProcess once they think they’re done, and use that the do the checks.
DynamicQueryAdapter yourbaq = new DynamicQueryAdapter(this.oTrans);
DataTable results;
yourbaq.BOConnect();
string baqname = "BAQNAME";
Ice.BO.QueryExecutionDataSet dsBAQ = yourbaq.GetQueryExecutionParametersByID(baqname);
dsBAQ.ExecutionParameter[0].ParameterID = "YOURPARAMETERNAME";
dsBAQ.ExecutionParameter[0].IsEmpty = false;
dsBAQ.ExecutionParameter[0].ParameterValue = VALUE FROM YOUR CONTROL AS A STRING;
dsBAQ.AcceptChanges();
yourbaq.ExecuteByID(baqname, dsBAQ);
if (yourbaq.QueryResults != null && yourbaq.QueryResults.Tables.Count > 0)
{
results = yourbaq.QueryResults.Tables["Results"];
}
else
{
results = new DataTable();
}
EpiDataView edv = (EpiDataView)oTrans.EpiDataViews[baqName];
if (!(edv != null))
{
edv = new EpiDataView();
oTrans.Add(baqName, edv);
}
edv.dataView = results.DefaultView;
Then either yourGrid.DataSource = results; or close and reopen the form and use the usual EpiBinding for the grid.
Edit - this is the simpler code version for ExecuteByID. If performance is a problem or you need to be able to update via the BAQ then you can shave a bit by using Execute instead, but there’s a bit more code involved.
This is good. One thing I also like to do is copy from the BAQ results then dispose of the DynamicQueryAdapter immediately so that the connection isn’t hanging around any longer than it has to. DataTable results; using(DynamicQueryAdapter yourbaq = new DynamicQueryAdapter(this.oTrans)) { // execution and copy within this block } // now create EpiDataView