Updateable BAQ

I have an Updateable Dashboard. There is only one field that is updateable. Issue is when someone updates the record, while another user has the dashboard open. When user1 saves, their data is saved!! Then User2 makes changes and saves. User1 changes are overwritten by User2.

How do I prevent this? What are some ways you have gotten this to work.

Thanks,

Ken

Put a Pre-Processing directive in the Update method of the UBAQ that compares Part.SysRev if they are different changes were made. Throw exception.

I am going to assume I can do this for OrderRel as well. I am not seeing where the tt is being set and used in the update. It looks like the whole query ds is being processed.

Should I even care about the trace log? I see my change. But I also see the queryDS being sent with more records than I updated.

  <paramDataSet name="queryResultDataset" useDataSetNbr="0">
      <changedValue tableName="Results" rowState="Modified" rowNum="0" colName="OrderRel_Character02"><![CDATA[hi]]></changedValue>
    </paramDataSet>

Partial

  <paramDataSetChanges>
    <paramDataSet name="queryDS" useDataSetNbr="0">
      <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="0" colName="Company"><![CDATA[EmbedTek]]></changedValue>
      <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="0" colName="QueryID"><![CDATA[ETK_SchedShipments]]></changedValue>
      <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="0" colName="SubQueryID"><![CDATA[f740c4f3-ed25-45ba-8373-340d4ac725b7]]></changedValue>
      <changedValue tableN....
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="ToTableID"><![CDATA[]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="ToFieldName"><![CDATA[]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="ToDataType"><![CDATA[]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="RValue"><![CDATA[_where-8587318048684276459]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="ExtSecurity"><![CDATA[False]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="SysRevID"><![CDATA[252276533]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="SysRowID"><![CDATA[d937b8f2-98a7-425b-8768-bc54a3cdcdfc]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="BitFlag"><![CDATA[0]]></changedValue>
  <changedValue tableName="QueryWhereItem" rowState="Added" rowNum="12" colName="RowMod"><![CDATA[]]></changedValue>
</paramDataSet>

You lost me there Ken. The UBAQ’s work via BPMS (even the standard BO based ones generate a BPM behind the scenes).
If you click on Advanced BPM option int eh UBAQ Update Processing you can check if the ttResult.SysRevID == the SYsRevID on the Db.

and if they are NOT the same that means that the data has changed and you should abort the update.

The BAQ is using BPM Update. Not Advance.

Wonder is that is part of the reason other fields are being updated.

That’s fine click on that BPM Directives Configuration Button
you can still add a PreProcessing method to the Update (that Epicor Generates)

ok closer.

Getting a type error on the following line. Is there a trick to do the compare?
if (ttResult.OrderRel_SysRevID == OrdRel.SysRevID)

Error CS0019: Operator ‘==’ cannot be applied to operands of type ‘long’ and ‘byte[]’

foreach (var ttResult in ttResults.Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P").Select(row => row) )
{
			using (var txscope1 = IceDataContext.CreateDefaultTransactionScope())
			{
				
				var OrdRel = Db.OrderRel.Where(ordr=> ordr.Company == Constants.CurrentCompany
								&& ordr.OrderNum == ttResult.OrderNum
								&& ordr.OrderLine == ttResult.OrderLine
								&& ordr.OrderRelNum == ttResult.OrderRelNum
								).FirstOrDefault();
								
								
				if(OrdRel != null)

				{
				   if (ttResult.OrderRel_SysRevID == OrdRel.SysRevID)
				   {
							OrdRel["Character02"] = ttResult.OrderRel_Character02;
							OrdRel["Date01"] = ttResult.OrderRel_Date01;
							Db.Validate();
				   }
				   else
				   {
						var message = "This Record has been updated by another User.  Please Refresh Dashboard and make your change again.";

						throw new Ice.Common.BusinessObjectException(
						new Ice.Common.BusinessObjectMessage(message)
						{
						Type = Ice.Common.BusinessObjectMessageType.Error,
						});
				   }
				}

				
				txscope1.Complete();
			}
}

You have to cast it to an int64 cause it’s a byte array. I’ll get you an example tomorrow

thanks.

I just tried result = Convert.ToInt64(OrdRel.SysRevID); and that did not work.

All right this was a giant pain in the ass LoL. Here is what you need to do
On the BAQ create a calculated field which will Cast the SysRevID to a BIG INT

Then on the BPM side Pre-Processing on Update get the current SysRevID and convert it also to a big int
Like this

var mycurrentRev = IPAddress.NetworkToHostOrder(BitConverter.ToInt64((from y in Db.OrderRel where y.SysRowID == x.OrderRel_SysRowID select y.SysRevID).FirstOrDefault(),0));

Note you will have to Click on Usings & References and add

using System.Net;

Then it is as simple as comparing the two values.

foreach(var x in ttResults.Where(r=>r.Updated()))
{
    var mycurrentRev = IPAddress.NetworkToHostOrder(BitConverter.ToInt64((from y in Db.OrderRel where y.SysRowID == x.OrderRel_SysRowID select y.SysRevID).FirstOrDefault(),0));
    if(x.Calculated_Calc_SysRevTT != mycurrentRev)
    {
        var message = "This Record has been updated by another User.  Please Refresh Dashboard and make your change again.";

        throw new Ice.Common.BusinessObjectException(
        new Ice.Common.BusinessObjectMessage(message)
        {
        Type = Ice.Common.BusinessObjectMessageType.Error,
        });
    }
}

Note do not do the actual updating here, let EPicor do the update in their “EpiMagical” base method. Your job is only in Pre-Processing to stop / raise an error if needed. Otherwise do nothing.

1 Like

ok I will try this out.

I think my other issue of data being saved is due to how the updateable BAQ is configured. That might be my next issue to investigate.

first need to solve this one.

Just in case it matters, a bigint in SQL server is a signed integer and the rowversion (SysRevID) value is an 8-byte array. SQL will cast it to a bigint, but if the SysRevID is high enough, the result will get flipped to a negative value, which a problem if you want to sort on the result.

In C#, you can convert the raw SysRevID value to a UInt64 (or unsigned long) like this:

UInt64 revId = BitConverter.ToUInt64(OrdRel.SysRevID.Reverse().ToArray(), 0);

3 Likes

Hi Jose,
I’m researching a solution to an issue where two separate users are entering data on the same updateable dashboard (separate fields) but on saving the data one is overwriting the other as they are both open at the same - one with new data in a field and the other data with old data.

I’ve resurrected this solution as it seems to be relevant to the problem I have. However I’m unable to figure out from the solution the BPM bit how it is implemented - can you help even though this is 4 years old :slight_smile:

A

i’m not @josecgomez but did implement this for a few UBAQs. Where is the roadblock?

Hi Ken I’m not fully sure where to place the two code sections … I know its in the BPM…

in the BAQ Editor on the Update → Update Processing Tab click the BPM Directive Configuration

Add a pre-processing directive to the update.

Add custom code widget

The code may need to be some tweaks depending on the tables you are using.

Thanks - that’s a big help! :grinning_face_with_smiling_eyes: