EnfusionDatabaseFramework icon indicating copy to clipboard operation
EnfusionDatabaseFramework copied to clipboard

A database framework to connect the Enfusion engine with SQL-, document- and local file databases.

Everon Life

Releases Arma Reforger Workshop License MIT

Enfusion Database Framework

Warning This framework is still in BETA. Until version 1.0.0 there is no backward compatibility guarantee! Expect some bugs/performance issues and function signature updates until then. Feedback via issue or discussion is welcome.

A database framework to connect the Enfusion engine with SQL-, document- and local file databases.

Note Are you trying to persist the entire world state and not just a few self scripted db entites? Consider using EnfusionPersistenceFramework which is built on top of this project.

🚀 Features

  • ✅ Easy to setup your DB entities with the provided base classes
  • ✅ Built-in GUID generation for DB entities to avoid expensive roundtrips to the database
  • ✅ Powerful query builder to find DB entities by complex conditions
  • ✅ Sync (blocking) and Async (non-blocking) APIs for adding/updating, finding, and removing DB entities
  • ✅ Pagination and result sorting by nested properties
  • ✅ Optional repository pattern for easy strong typed results and re-useable queries.
  • 🚧 Migrations between storage backends e.g. JsonFile <-> Http:MySQL

Drivers

  • InMemory for unit testing purposes
  • JsonFile local .json files for workbench development and small data volumes
  • BinaryFile local .bin files, same purpose as JSON but much smaller in filesize.
  • 🚧 BIBackend local/cloud synced .bin files stored in the Bohemia Interactive session backend.
  • 🚧 Http a web API proxy to other external storage services such as SQL and document databases.
    • ✅ Document Databases MongoDB
    • 🚧 SQL Databases SQLite, MySQL, PostgreSQL

📖 Documentation

Detailed information on the individual classes and best practices can be found here.

⚡ Quick start

[EDF_DbName.Automatic()]
class TAG_MyPersistentInfo : EDF_DbEntity
{
    float m_fNumber;
    string m_sText;

    //------------------------------------------------------------------------------------------------
    //! Db entities can not have a constructor with parameters, this is a limitation of the engine.
    //! Consult the docs for more info on this.
    static TAG_MyPersistentInfo Create(float number, string text)
    {
        TAG_MyPersistentInfo instance();
        instance.m_fNumber = number;
        instance.m_sText = text;
        return instance;
    }
};

class EDF_QuickstartAction : ScriptedUserAction
{
    //------------------------------------------------------------------------------------------------
    override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
    {
        // Get the connection info as an attribute or parse it from CLI params etc.
        EDF_JsonFileDbConnectionInfo connectInfo();
        connectInfo.m_sDatabaseName = "MyJsonDatabase";

        // Get a db context instance and save it somewhere to re-use in e.g. a singleton
        EDF_DbContext dbContext = EDF_DbContext.Create(connectInfo);

        // For convenience interact with the DB context through a repository
        EDF_DbRepository<TAG_MyPersistentInfo> repository = EDF_DbEntityHelper<TAG_MyPersistentInfo>.GetRepository(dbContext);

        // Add some entries
        repository.AddOrUpdateAsync(TAG_MyPersistentInfo.Create(13.37, "Hello"));
        repository.AddOrUpdateAsync(TAG_MyPersistentInfo.Create(42.42, "World!"));

        // Now find hello
        EDF_DbFindCondition condition = EDF_DbFind.Field("m_sText").Contains("Hello");
        EDF_DbFindCallbackSingle<TAG_MyPersistentInfo> helloHandler(this, "FindHelloHandler");
        repository.FindFirstAsync(condition, callback: helloHandler);
    }

    protected void FindHelloHandler(EDF_EDbOperationStatusCode statusCode, TAG_MyPersistentInfo result)
    {
        PrintFormat("FindHelloHandler invoked! - StatusCode: %1",
            typename.EnumToString(EDF_EDbOperationStatusCode, statusCode));

        if (result)
            PrintFormat("Result: %1(id: %2, number: %3, text: %4)",
                result, result.GetId(), result.m_fNumber, result.m_sText)
    }
};

You should see this in your script console after executing the user action

FindHelloHandler invoked! - StatusCode: SUCCESS
Result: TAG_MyPersistentInfo<0x0000020D41100670>(id: 646e0c40-0000-0000-32cd-65805811b000, number: 13.37, text: Hello)

And in your profile find these two files

  • profile/.db/MyJsonDatabase/MyPersistentInfos/646e0c40-0000-0000-32cd-65805811b000.json
  • profile/.db/MyJsonDatabase/MyPersistentInfos/646e0c40-0000-0001-1a8d-352051eea400.json

And inside 646e0c40-0000-0000-32cd-65805811b000.json

{
    "m_sId": "646e0c40-0000-0000-32cd-65805811b000",
    "m_fNumber": 13.36999,
    "m_sText": "Hello"
}