Creating Dynamic Connection Strings
A dynamic connection string is a connection string that is resolved at the time the database connection is opened, rather than at the time the connection string is defined. This is useful in SaaS applications where client data is stored in different systems of record located on different servers.
Dynamic connection strings can be created in Alpha Anywhere in one of two ways: by defining a connection string using the DynamicConnection_ prefix or using the ::EVAL:: prefix, which allows you to define an Xbasic function or expression that is used to dynamically calculate the connection string.
Dynamic connection strings can be defined using a prefix. A connection string named "DynamicConnection_<name>", where <name> is a user-defined string identifying the connection string, will be resolved dynamically at runtime. For example:
In the dynamic connection string above, the <name> is "MyCustomApplication".
The actual value of the dynamic connection string is resolved by referring to a session variable called session.__protected__<name>. For the dynamic connection string defined above, the session variable would be as follows:
The value of session.__protected__<name> defines the actual connection string to be used.
The value of this session variable is typically set when the user logs into the application. For example, it could be set to a named connection such as:
Dynamic connections can be used directly in Grid and UX components but may not work as expected in .a5w pages or Xbasic scripts when using the SQL::Connection object. A connection string with the DynamicConnection_ prefix cannot be used with the SQL::Connection open function. Instead, you must use the a5SQLConnectionOpen() function, which will evaluate the dynamic connection string before opening the connection. For example:
session.__protected__conn = "::Name::myConnStr" ' change to any existing named connection string dim cn as sql::Connection if (a5SQLConnectionOpen(cn,"::Name::DynamicConnection_conn",session)) then dim tables as c = cn.listTables() cn.close() ui_msg_box("Tables in Database", tables) else ui_msg_box("Error Opening Database", "Could not open connection. Error was: " + cn.callResult()) end if
Dynamic connection strings can also be created using the ::EVAL:: prefix. The ::EVAL:: prefix is used in the named connection string, similar to how the ::Name:: prefix is used for named connections.
Prefixing a connection string with ::EVAL:: causes the connection string to be evaluated as an Xbasic expression.
For example, consider the following connection string:
When an AlphaDAO connection is opened using the above string, the MyFunctionThatReturnsAConnString() is evaluated and the return value (which would typically be a named connection string with the ::Name:: prefix) is used as the connection string.
The Xbasic function called by ::EVAL:: can be a global Xbasic function or a function defined in an Xbasic Module for a web project.
It may not be possible to create a global Xbasic function in a web application. Therefore, you need to use an Xbasic Module.
Functions defined in an Xbasic Module can be referenced in the ::EVAL:: expression using the require() function. For example, assume an Xbasic Module called 'module1' has been defined with a function that computes the connection string named 'getConnectionString'. This function can be used with the ::EVAL:: as shown below:
In addition to making function calls, inline Xbasic expressions can also be used with the ::EVAL:: prefix. This was demonstrated in the previous example showing how to use functions defined Xbasic Modues to dynamically compute the connection string. In this next example, the dynamic connection string uses an inline Xbasic if expression to compute the connection string:
::EVAL::if(customer = "Fred","::name::Fred","::name::EverybodyElse")
The ::EVAL:: prefix is supported directly by the open() method for a SQL::Connection object. For example:
dim customer as C = "" 'uncomment the line below to see what happens when customer = "Fred" 'customer = "Fred" dim connStr as c = <<%str% ::EVAL::if(customer = "Fred","::name::Fred","::name::EverybodyElse") %str% if (cn.open(connStr)) then dim connStr as c = cn.GetConnectionString() cn.close() ui_msg_box("Connection string", connStr) else ui_msg_box("Error Opening Database", "Could not open connection. Error was: " + cn.callResult()) end if