Replies: 4 comments 8 replies
-
@MikeStall |
Beta Was this translation helpful? Give feedback.
-
I agree that intellisense could be very nice, especially in environments where there are a large number of EVs such as one that includes the CoE. But we can already get to EVs by just adding environmentvariabledefinition and environmentvariablevalue to our app as datasources. Yes, that doesn't come with intellisense but that seems like a small marginal benefit when you consider that some very large percentage of apps out there do not use EVs: seems odd to require that they eagerly load all definitions--or eagerly fetch values as well--if they aren't using any. |
Beta Was this translation helpful? Give feedback.
-
It would be very interesting if the intellisense would pick up the solution the app is in to help the user find the right value. |
Beta Was this translation helpful? Give feedback.
-
Oh yes please! But maybe it's not only an PowerFx issue, since we need the same features for PlugIns (and even better, also for form scripting api). |
Beta Was this translation helpful? Give feedback.
-
Here is a proposal for #2416 - for accessing Dataverse Environment Variables directly from Power Fx expressions in a strongly-typed, discoverable way.
This is primarily intended to support Dataverse Environment Variables, as defined here: https://learn.microsoft.com/en-us/power-apps/maker/data-platform/environmentvariables . But since it goes through host abstractions, it should be usable in other ways.
The intention is to provide a common language experience across Power Platform products - and so absorb as much policy as possible in the Fx layer rather than the host. For example, Fx should deal with name disambiguation so that it's done consistently across products.
Requirements
The host:
Existing Art
Today, the Env Vars live in a Dataverse table and can be accessed directly via a table lookup:
LookUp('Environment Variable Values', 'Environment Variable Definition'.'Schema Name' = "test_environment_data").Value
And the proposal is to write:
Environment.Variables.TestData
where it's strongly typed to number,date,bool,etc.So we're improving on this experience with simpler access, stronger typing, better discoverability, and display names. Also least-privilege - the maker no longer requires full access to query and enumerate the variable table at runtime.
In Copilot Studio, you can access env variables via
Env.logicalname
. This provides a similar experience to this proposal except that it a) usesEnv
instead ofEnvironment
, b) uses logical names instead of display names.Language level experience:
When enabled, makers can access an object
Environment.Variables
, which is a record where each field is a strongly typed environment variable.For example, suppose the host has defined a number variable called MaxCount. An expression could access the value as
Environment.Variables.MaxCount
and use it like a normal number variable in expressions likeIf(Environment.Variables.MaxCount > 50, "too high")
A key win here is good intellisense and authoring: the maker should get completion after
Environment.Variables.
and see the list of possible variables.This is also a regular immutable record, with similar properties to the
User
object.Like User, it can be aliases in With, like
With({vars : Environment.Variables}, vars.MaxCount)
The values are "current" and a runtime fetch. The host does not need to eagerly fetch and cache. This means that the values should be considered volatile and could change through the lifetime of an expression (like
Now()
).Display Names
The Power Fx type system supports display names and this feature can follow existing semantics:
Runtime errors
Since accessing a variable is ultimately fetching from an external source, it's always possible for that to fail at runtime. While the strong typing approach here should help makers avoid common errors (typos in the var name), there are inevitable corner cases, such as if a variable was deleted at runtime (after passing design-time checks) or just a plain network failure.
Errors will return an ErrorValue, which will naturally propagate through the expression via data flow semantics unless caught by an IfError.
For example, suppose accessing MaxCount failed at runtime, then:
Environment.Variables.MaxCount
Environment.Variables.MaxCount > 50
IsError(Environment.Variables.MaxCount)
true
Compile-time errors:
Environment.Variables
if the host has not enabled environment variables.User
object.Dataverse details.
This feature is general purpose, but should be sufficient to fully handle Dataverse env vars.
Dataverse env vars have display and logical names.
They are strongly typed. Most of the types have an obvious mapping to Power Fx (decimal, text, two option --> boolean). Json is mapped as Untyped Object (similar to ParseJson).
Hosting APIs.
Key criteria for hosting:
In this pattern,
Environment.Variables
is literally just a RecordValue. That already has all the essential patterns we need:So the APIs can be:
At design time, add to the symbol table:
var slot = symbolTable.AddEnvVariable(recordType); // adds with "Environment.Variable" name
And at runtime, pass the corresponding values:
symbolValues.Set(slot, recordValue);
Refresh
Runtime fetch calls out to the host to get the latest value.
But suppose the host needs to refresh the list of variables during design time.
It can just refresh the symbols using existing symbolTable APIs. For example, it could:
Dataverse Helpers
We can have helpers to aide in creating the RecordType/RecordValue from a dataverse IOrganizationService
RecordType would be a static type (since the variable list is fetched eagerly), but the RecordValue here would be a derived class that override TryGetField, etc and invoke on dataverse.
Beta Was this translation helpful? Give feedback.
All reactions