Since Business Central 2021 Wave 1 – v18, if you will – we are able to return about ANY type from a procedure. For many languages, that’s the most normal thing, but for Business Central’s AL language, it was not. So, at the time this was announced, many people were ecstatic and talking about it in sessions, on blog posts, on Twitter and so on.
And me as well. In fact, I did a session on the Dutch Dynamics Community, and one for Directions. The one for Directions was recorded and shared on the Directions Community Portal, and you can find the recording here: Webinar Preparing For The Future With Business Central . At 45:19, I start explaining the “Complex Return Types”.
Well .. since you can simply watch the recording, and since it’s much easier to explain it in a video in stead of writing a blog post, I’m going to let you watch the recording for the specifics around what “Complex Return types” are for Business Central.
What I wanted to focus on in this post – and what I didn’t realize at the time I did those sessions – was the reason behind the fact that it seemed to be so hard to really work with records. So .. let me try to explain why it’s behaving the way it does.
Well, consider a function that would return a filtered set of records:
It would make it so easy to get all subrecords from some kind of main record, like in this case:
Thing is – how do you work with it? If I get back a set of records, I most likely would either like to filter some more, and/or loop it, right? Well, I hope you can understand that this absolutely doesn’t make any sense:
Every next would re-get the set of records, so … endless loop it is 😉.
Well, in a way, this would make sense:
Although, when assigning a Rec to a Rec, it does NOT take over the filters. So, it might make sense, but no way it works, it simply would loop ALL records in the sales lines table.
I hear you thinking – no problem, there is a “copyfilters” statement, so let’s do that! Well, no, and this time, the reason is because that method – for some reason that I can’t wrap my head around – needs a “ByRef” variable .. which I don’t have as a return type, obviously:
And before you ask – same for the copy-method:
Last that I could think of is working with the “GetFilters”. Thing is, there isn’t something like “SetFilters”, only “SetFilter” (singular). So not really generic. I can imagine a way to do this with RecRef/FieldRef, like starting some kind of loop like this:
.. but in all honesty, that’s starting to kind of beat the purpose, doesn’t it? I kind of refused to dive into this much further as I couldn’t see it as performant as it should be either.. . If I’m wrong – please I’m all open for feedback!
And let’s be honest, it seems that simply removing the “byref” necessity on the copyfilters-method would solve this problem .. 🤔.
A named return variable, or not a named return variable, that’s the question!
That’s another question we could ask ourselves indeed. And .. does it really matter? Well, I can tell you, it absolutely does matter. It’s something we wouldn’t really think of – at least I wouldn’t – but when thinking about it, it actually does make sense on how it reacts.
What I’m talking about? Well, let’s consider the difference between option 1:
And option 2:
These two functions give a very different outcome. And that’s because the return mechanism is very different in both functions.
In option 1, you actually put the filter on the variable that is being returned.
In option 2, you put it on the local var, but then an assignment of that local var happens on the return-var. So as such, you do a Rec := Rec .. which .. loses your filters. Remember?
The difference in execution can simply be shown by counting the end-result. Like this:
Option 1 will be the expected result: in my case, 1 sales line:
Although option 2 will lose the filter, so it returns a count of all Sales Lines:
So – be careful when you’d apply this to a ModifyAll or DeleteAll or something like that 😜.
This assignment-behaviour obviously applies to all types. Not just records. Though, I can only think of records suffering from immediate consequences .. may be there are other types that need special attention as well, I don’t know.
Complex Return Types are very useful. Coming up with useful patterns though, is somewhat more challenging. This one pattern for sub-records I would love to be accessible .. So I wouldn’t mind Microsoft to “fix” the ByRef need for CopyFilters.
Or if I’m missing something, I wouldn’t mind to understand what and why ;-). All feedback is always welcome ;-). I at least hope it kind of explains a bit to you as it did to me ;-).