Functions data context

I’m trying to be forward-thinking and create the bones of a solution using the new Functions.

In a BPM, I’d do what I’m doing using a ServiceContract, but that requires a datacontext and the usual “Db” says it doesn’t exist. Anyone know how this is supposed to be done?

Documentation on Functions seems to be quite thin so far.

1 Like

It is the same as BPM with one caveat at the end.

In a code widget, hit Ctrl+Space and you get the intellisense on tables and you can write LINQ as you will:

The change with Functions is we are building a new data model specific to the Function - not everything in the database. You opt in to which tables you want:

2 Likes

Thanks, that’s useful. It seems Db is only valid at all if you have at least one table in the References part.

I’m trying to use ServiceRenderer, though, and while adding a single table to the library means that Db is now recognised as existing, I still can’t use it in ServiceRenderer.GetService because I’m getting “cannot convert to Ice.IceDataContext”.

Is this whole approach wrong?

You want to call another BO in code as opposed to the invoke bo widget? That’s really the model you want to leverage.

Yes, ideally.

I don’t have to in this case, but it’s proved a tidy way of working elsewhere so it would be nice to know it can be done and if so how.

I think for the moment we’re going to retreat from Functions.

For us, the need for them is most obvious when there’s something non-standard that might be called on in several places. Generally, non-standard functionality needs code, and it’s just too restrictive if you need to break the code up to return to widgets.

Our case here, just to provide the real-life background:

We have had a new carrier sprung on us very suddenly, and our Logistics department work at speed so they need an integration to handle the carrier data in the background. We did this for our main existing carrier using BPMs dedicated to just them, using custom code for REST calls. A second carrier option means it’s now obvious that we should make that functionality more generic, plus the API documentation for the new one warns that although they’re currently using SOAP, they plan to move over to REST - further reason to make sure that functionality is abstracted from the more general integration flow.

In both cases, we get an authentication token back from an initial log-in on the external system which has a validity period. What we do for these types of integrations is to store the token and expiry as Epicor user codes, so any process needing the token queries first the user code, then, only if needed, the external authentication service. Until now, we’ve built this into a uBAQ in each case, where custom processing in GetList takes the appropriate action in providing the user codes requested or first updating them from the external service - the other parts of Epicor don’t need to know, we just use DynamicQuery on the relevant BAQ.

Functions feel much more “correct” for this kind of thing (and we were hoping to include the whole functionality in one library), but the interaction between the Epicor storage and the unavoidable custom code means it gets tangled very quickly as things stand, and in practice our existing uBAQ system seems more practical.

It seems Db is only valid at all if you have at least one table in the References part.

Documentation explicitly says that.

I’m trying to use ServiceRenderer, though, and while adding a single table to the library means that Db is now recognised as existing, I still can’t use it in ServiceRenderer.GetService because I’m getting “cannot convert to Ice.IceDataContext”.

You shouldn’t use ServiceRendere with EFx. If you need to call service from custom code, you have to use CallService method instead. Something as the following

TipTableset ts = null;
this.CallService<Ice.Contracts.TipSvcContract>(
    bo =>
    {
        ts = bo.GetByID("EP", 13);
    });

Regarding Db context.
It is not Ice or Erp context. It is custom “context” which in the future could become completely independent from Ice/Erp contexts. So it cannot be used with ServiceRendrer. Moreover, since functions could be executed outside of ERP application host, it should not rely directly on implementation details of ERP service hosting approach. Db as a parameter of ServiceRenderer.GetServie method is the leaking abstraction.

1 Like

I’m interested to hear that there is documentation. Where can I find it?

1 Like

Do you mean CallService?

It is not documented. And I don’t think it even should be a part of documentation.

  1. We don’t treat custom code blocks as main way to call services in workflow-based functions
  2. It is an advanced scenario. So it could be a part of educational materials, but not a part of documentation itself. Otherwise only BPM/EFx need few hundreds pages to explain all how-tos .
  3. You can look at the generated code and learn how we generate calls for the Invoke BO method widget. Actually, I never recommend it, since we can change our generators without any notifications. But it works in general.

Actually, I meant your earlier comment about Db “Documentation explicitly states that”.

But, while I take your point about the amount of documentation needed for BPMs etc, I for one would happily trade every promised feature in the next two or three versions of E10 for exactly that documentation. New features are nice, but given the choice between more things the system can do, and clear explicit technical documentation of what’s already there, I’d opt for the second every single time.

2 Likes

Can you share the link to publicly available documentation (if any)? I know only internal one.
I’ll try to point to the article

Regarding documentation in general. As I wrote above, calling services form custom code block of workflow-based function (or directive too) is advanced scenario.
If you are really sure of the need for such a thing in the documentation, please create official request to our support with clear justification (e.g., lack of this information blocks us from the migration for BPM to Functions).

This is the only documentation I know of that covers Functions:

ICE Tools User Guide

I won’t put in any official request for documentation for specific features, because there’s no way that approach can cover everything. It’s just quite frustrating, working with Epicor in the real world where you never know what the next demand is going to be, when you hit a limit you didn’t know was going to be there and find that beyond that you need secret knowledge.

  1. It looks funny, but I have no access rights to this public server (or to the pdf)

  2. Sorry, but it happens with virtually any product on market. While you use standard approaches, you can pretty easily find documentation/samples/etc. As far as you need something non-standard (and direct usage of ServiceRenderer is not standard) you enter into the uncharted lands. And this forum (like stackoverflow for general dev) is one of the ways to simplify own life. And our (as product developers) too, since it is actually the only way to get direct feedback.

@dhewi I’ve already asked our tech-writer to share this pdf with me.

Thanks for your time and effort anyway.

For now I’m going to leave Functions until there’s a bit more community knowledge developed. At the moment I can’t think of many cases where using them will be sensible relying only on widget flows, and deadlines don’t allow for me finding out what I’ll need to know otherwise.

I was hoping that I could move existing processes across, but clearly that isn’t going to happen because it’s too fundamentally different and they won’t work. At least I know that now.

It would be nice if you share patterns which you need. You can send a mail to me directly.
Anyway, we released very first version of completely new subsystem (Functions) in 10.2.500. So, definitely it will grow and become more functional in upcoming releases.

Thanks.

I need to get this current urgent need out of the way in ways I can already do, then hopefully I’ll have a chance to look at how it might be done with Functions. That way there will be a clearer comparison.

Thanks. I hope we will have a chance to continue our conversation in the future

I am using below code in BPM to get cost. I would like to convert to Functions but its not working as this.DB context s not valid.
Erp.Internal.Lib.InvCosts _InvCosts = new Erp.Internal.Lib.InvCosts(this.Db);