I Would like to know if the Genexus Extension SDK already implements something to store persistent data locally (KB Independant and per KB), something like PersistentDictionary
from ManagedEsent
We don't use PersistentDictionary
. I would advice not to use it, as it's a Windows specific API, and we are trying make everything new cross platform, as part of our journey of making GeneXus BL run on other OS.
There are different options of persistence, depending on the specific details of your scenario.
If you want to store something like configuration settings for your extension, you can use the ConfigurationHelper
class located in Artech.Common.Helpers
. This class provides read access to the configurations defined in the GeneXus.exe.config
file in the GeneXus installation folder, as well as read/write access to the Environment.config
file located in %AppData%\GeneXus\GeneXus\<version>\Environment.config
. Note this file depends on the current user, and is shared between different GeneXus instances of a same main version.
The ConfigurationHelper
class provides operations to read and save settings of basic types string
, int
and bool
.
const string MY_EXTENSION = "MyExtensionSettings";
const string SETTING1 = "Setting1";
const string SETTING1_DEFAULT_VALUE = "This is the default value";
const string SETTING2 = "Setting2";
const int SETTING2_DEFAULT_VALUE = 20;
string setting1Value = ConfigurationHelper.GetUserSetting(MY_EXTENSION, SETTING1, SETTING1_DEFAULT_VALUE);
int setting2Value = ConfigurationHelper.GetUserSetting(MY_EXTENSION, SETTING2, SETTING2_DEFAULT_VALUE);
// Do something and maybe change the setting values
ConfigurationHelper.SetUserSetting(MY_EXTENSION, SETTING1, setting1Value);
ConfigurationHelper.SetUserSetting(MY_EXTENSION, SETTING2, setting2Value);
If you want to store something in a file based on the current opened KB, there's no specific API that'll help you handle the persistence. You can use the properties Location
and UserDirectory
of the KnowledgeBase
class to access the KB location or a directory for the current user under the KB location, but it's up to you the handling of the file. You'll have to decide on the file format (binary or text), file encoding in case of text files, and handle all read and write operations to that file.
We use the kb.UserDirectory
path to store non-critical stuff, such as the set of objects that were opened the last time the KB was closed, or the filter values for different dialogs.
In case you'd like to store settings inside the KB, there are plenty of options.
KBObjectPart
, define your part in a BL package, declare that the part composes objects of certain type, and provide an editor for your new part in a UI package. KBObjectPart
extends Entity
so the serialization of the part is similar as in the previous case. A caveat of this option is that you'll also have to handle how the part content is imported, exported, and compared.KBObject
class, which extends Entity
. Objects are not obliged to have parts (for instance the Folder object doesn't have any). When choosing to provide a new kind of object you have to consider a couple of things, such as:
As a general guideline, if you choose to add a new property, add it to objects, versions, or environments, not parts. Adding properties to parts is not so good for discoverability. Also if you choose to add a new kind of object, even though it inherits from Entity
which as mentioned earlier can read and store a byte array, it's preferred to don't use the byte array in KBObject
and add a KBObjectPart
to it instead. That way the KBObject
remains as lightweight as possible, and loading the object definition from the DB remains fast, and the blob content is loaded only when truly needed.
There's no rule of thumb. Depending on the specifics of the scenario, one option may be more suited than others.