I am trying to assign Data Tags to parts within a Function via custom code. The idea is to schedule this function to run however often, and I can later query the parts in a BAQ based on whether they have the “archive” tag. The query below is just the start of a much more complicated query, but does anyone know how to actually assign the tag?
var query = from part in Db.Part.Where(p => p.InActive == false)
select new { part };
foreach(var p in query)
{
if(p.part.RunOut == false && p.part.OnHold == false)
{
// add Data Tag
Ice.BO.SysTagDataSet ds = new Ice.BO.SysTagDataSet();
this.CallService<Ice.Proxy.BO.SysTagImpl>(ts => ts.GetNewSysTag(ds));
foreach(var tag in ds.SysTag)
{
//this.CallService<Ice.Proxy.BO.SysTagImpl>(ts => ts.Update(ds));
}
}
}
I’m not sure if I should be using Ice.BO.SysTagDataSet, or a “tableset” which I’ve seen in other places, but that is what’s called in the trace file.
Hey Kevin,
Everything works up until the Update method.
var query = from part in Db.Part
where part.PartNum == "F4780"
select new { part };
foreach(var p in query)
{
// add Data Tag
//Ice.BO.SysTagDataSet ds = new Ice.BO.SysTagDataSet();
//this.CallService<Ice.Proxy.BO.SysTagImpl>(ts => ts.GetNewSysTag(ds));
//this.CallService<Ice.Proxy.BO.SysTagImpl>(ts => ts.Update(ds));
CallService<SysTagSvcContract>(st =>
{
SysTagTableset stTS = new SysTagTableset();
SysTagRow newTag = new SysTagRow()
{
Company = "TEI",
ForeignSysRowID = p.part.SysRowID,
ForeignTableName = "Part",
Tag = "ArchiveCandidate",
CreatedOn = DateTime.Now,
CreatedBy = "JPoston",
IsShared = true,
RowMod = "A"
};
stTS.SysTag.Add(newTag);
st.Update(ref stTS);
});
}
But I get this exception when I include the Update method.
Where would you go from here, or what should I be looking into next to figure out what’s wrong? This was run from the “Schedule Epicor Function” menu item.
I’m speechless… Thank you, that fixed it, and everything is working now. I really don’t know how you guys learn all this stuff. The Field Help for that checkbox doesn’t provide any information on what its for. Maybe it does in a later version. But I can’t thank you enough. Thanks again!
Just FYI, if you’re looping through things and need a transaction, and there’s a chance a that an iteration will fail, create a TransactionScope for each loop instead of just using the “use Transaction” checkbox.
Checking the box on the function will revert all changes if even one loop fails. Something like the code below will continue on to the next iteration while recording what failed.
Note that you do not check the Transaction box AND create a txScope in your code. One or the other.
foreach(var thing in things)
{
try //So the whole thing doesn't die on a single error.
{
using (var txScope = IceContext.CreateDefaultTransactionScope())
//Creates a Transaction for just this one iteration.
{
MethodCall();
AnotherCall();
txScope.Complete(); //Close out transaction
}
}
catch (Exception e)
{
ErrMsg += SomeKeyField + ":" + e.Message + Environment.NewLine;
//ErrMsg would be an output on your function.
//You could log any number of ways too.
//This was just what I used on the code I copied this from, which was a batch process.
}
}
I’m always a little lost on Transaction scope (when it’s required, when it’s not required but probably should be used and why, etc.) If someone wanted to stick an explainer in the Experts Corner some time, that’d be helpful.
@ErpJohn
Just in case you missed it, you can check out how the system does it by dumping the sources and using the widgets in bpms and functions , then going to server/bpms folder to review the generated code, that’s how a lot of learnt.
In earlier versions you needed to had to edit the hosts.Config or the Web.Config.