Hello, i’m in need of some input on LINQ coding for BPMs. I’m currently building a large BPM that uses a UDTable, over and over again and updates it at various points. Let’s say I use the code:
Ice.Tables.UD20 UD20;
using (var txScope = IceContext.CreateDefaultTransactionScope())
{
if (Thing == “WhatIWant”)
{
foreach (var UD20_iterator in (from UD20_Row in Db.UD20
where UD20_Row.Company == Session.CompanyID &&
UD20_Row.Key1 == “asdf”)
select UD20_Row))
{
UD20 = UD20_iterator;
UD20.Key1 = “asdf”;
Db.Validate();
}
}
txScope.Complete();
}
Simple enough, but let’s say I use UD20 twice here for various reasons. I know I’m oversimplifying, but i’m doing it on purpose because it’s hard for me to explain.
Ice.Tables.UD20 UD20;
using (var txScope = IceContext.CreateDefaultTransactionScope())
{
if (Thing == “WhatIWant”)
{
foreach (var UD20_iterator in (from UD20_Row in Db.UD20
where UD20_Row.Company == Session.CompanyID &&
UD20_Row.Key1 == “asdf”)
select UD20_Row))
{
UD20 = UD20_iterator;
UD20.Character01 = “xyz”;
Db.Validate();
}
}
if (Thing == "a different thing")
{
foreach (var UD20_iterator in (from UD20_Row in Db.UD20
where UD20_Row.Company == Session.CompanyID &&
UD20_Row.Key1 == "doa")
select UD20_Row))
{
UD20 = UD20_iterator;
UD20.Character01 = "qwer";
Db.Validate();
}
}
txScope.Complete();
}
In the code above, i’m using the “UD20” variable twice. I believe (but i’m not sure) this will cause conflicts eventually. I’m already using the variable for the data retrieved on the query for “asdf” and then I use it again for the data for “doa”. I’m sure my simplistic example wont cause issues, but what if I’m using my Ice.Tables.UD20 UD20 variable 10 or more times in my code? Is there a simple way to clear the UD20 variable each time before I use it? Do I need to clear it? Am I worrying about something I shouldn’t? I want to avoid having to do setup multiple variables as the same thing. Something like this:
Ice.Tables.UD20 UD20a;
Ice.Tables.UD20 UD20b;
using (var txScope = IceContext.CreateDefaultTransactionScope())
{
if (Thing == “WhatIWant”)
{
foreach (var UD20_iterator in (from UD20_Row in Db.UD20
where UD20_Row.Company == Session.CompanyID &&
UD20_Row.Key1 == “asdf”)
select UD20_Row))
{
UD20a = UD20_iterator;
UD20a.Character01 = “xyz”;
Db.Validate();
}
}
if (Thing == "a different thing")
{
foreach (var UD20_iterator in (from UD20_Row in Db.UD20
where UD20_Row.Company == Session.CompanyID &&
UD20_Row.Key1 == "asdf")
select UD20_Row))
{
UD20b = UD20_iterator;
UD20b.Character01 = "asdf";
Db.Validate();
}
}
txScope.Complete();
}
I hope this makes sense. Thanks for your input. I’m hoping i’m just being silly.
A few different things you can do here and some may be version dependent (i.e. using Functions in 10.2.500). You can do something like this - basically one function that you can call anywhere in the code and pass in the value and the key you want to update. Just a quick example. You could also even pass in the name of the column you wanted to update (i.e. Character01, Character02, whatever_c). You could also us the BO to perform the updates as well vs. this method.
I have finally gotten so that I can write nearly any query “from my head”… There are good ways and bad ways.
Here is your code with how I would do this.
your concern about reusing the variables is not really a problem IF you have them inside curly brackets… any new variables you define are disposed of at the end of the curly bracket. C# is very good about telling you if you tried to redeclare something that is already declared.
you do NOT need to declare the “ice.tables.ud20” line at the top… when you do the query it automatically does this.
It is best to do the query first, and THEN do a foreach with the results. Note that you also do not need to use that old-style “iterator” logic where you assign an iterator, and then reassign it to a second variable. This came from old conversions from ABL.
OH, and I converted the queries into Lambda statements because the code becomes a lot shorter… Yes, these short one-line statements return the same exact thing as your 4 line statement. Also, CompanyID is the same shortcut to Session.CompanyID.
//Ice.Tables.UD20 UD20; <-This is not needed
using(var txScope = IceContext.CreateDefaultTransactionScope()) {
if (Thing == “WhatIWant”) {
var ud20RowsToUpdate = Db.UD20.Where(x => x.Company == CompanyID && x.Key1 == "asdf");
foreach (var ud20 in ud20RowsToUpdate) {
UD20.Character01 = “xyz”;
Db.Validate();
}
}
if (Thing == "a different thing") {
var ud20RowsToUpdate = Db.UD20.Where(x => x.Company == CompanyID && x.Key1 == "doa");
foreach (var ud20 in ud20RowsToUpdate) {
UD20.Character01 = "qwer";
Db.Validate();
}
}
txScope.Complete();
}
ALSO… lets say that you wanted to do multiple queries and reuse variables, but they were not inside if statements like above… here is what it would look like… simply leave off the “var” at the beginning of the second query:
You guys are all great! Thank you; I’m happy I overthought it! I was fearful of having to go back and add an absurd amount of variables. I’m in love with the function route! Fantastic stuff for heavy hitting BPMs.
Hey… if I said “I figured it out in a day”… THAT would be showing off… It took me months to get my head wrapped around this vs the old way we did this in Progress ABL code. hahah