Code Generation (Extension classes)

Description

Main purpose of these classes - is to be used as table rows instead of generic BGEntity class.

This is the main type of Code Generation. It removes all boilerplate code and provides super easy and slim API for accessing table rows and their fields. You can enable this type of code generation by using CodeGen addon

Advantages of using CodeGen

  1. No boilerplate code
  2. Fastest available method for accessing field values
  3. IDE auto-completion support
  4. Compile time check (if field names are changed you'll get compilation error)

Details

Accessing fields without CodeGeneration

Accessing fields with CodeGeneration

Accessing rows without/with CodeGeneration

More Details

Generated classes are inherited from generic BGEntity class. These classes can not be added to GameObject, because they are not Unity's MonoBehaviour (there are also another generated classes, which can be added to GameObjects, learn more here). When this CodeGen is enabled, database populated not with basic BGEntity objects, but with these extension classes. So when you access database like this var entity=meta[0]; entity variable has this extension type with all the fields generated as properties.

Additionally, you will get all table(meta) methods alternatives as static methods of that particular class (see the table below for more information), so instead of this, for example:

    var repo = BGRepo.I;
    var meta = repo["MyTable"];
    BGE_MyTable entity = (BGE_MyTable) meta[new BGId("HThOdRCxlEGU1aefSG+Nbw")];
you can write code like this:
    BGE_MyTable entity = BGE_MyTable.GetEntity(new BGId("HThOdRCxlEGU1aefSG+Nbw"));

using generated BGE_MyTable class.

What is generated, exactly?

We will use MyTable as a table name (generated class name) and 2 fields (name string, gold int) for illustration purpose.

Method/property name Static Description
{field_prefix}{FieldName} No Properties are generated for each table field. Each property has the same type as corresponding database field. Use these properties to read/write values from/to database
    MyTable firstRow = MyTable.GetEntity(0);
    //name is generated property for "name" field
    string name = firstRow.name;
GetEntity() Yes 3 static methods for getting table row by Index/ID/Name.
    // get the first row
    MyTable firstRow = MyTable.GetEntity(0);
    // get the first with specified ID
    MyTable rowByID = MyTable.GetEntity(new BGId("SomeID"));
    // get the first row with name="SomeName"
    MyTable rowByName = MyTable.GetEntity("SomeName");
NewEntity() Yes Static method for adding table row.
    //new row is added
    MyTable newRow = MyTable.NewEntity();
ForEachEntity() Yes Static method for iterating over table rows. The parameters are:
  1. Action<MyTable> action : Action to execute for each row
  2. Predicate<MyTable> filter : Optional filter to filter out the rows
  3. Comparison<MyTable> sort : Optional sorter to sort the rows
// print every entity name
MyTable.ForEachEntity(
    entity => Debug.Log($"Entity={entity.name}")
);
// print entity name for each entity, which gold field more than 0
MyTable.ForEachEntity(
    entity => Debug.Log($"Entity={entity.name}"),
    entity => entity.gold > 0
);
// print entity name for each entity, which gold field more than 0,
// entities are sorted by name
MyTable.ForEachEntity(
    entity => Debug.Log($"Entity={entity.name}"),
    entity => entity.gold > 0,
    (e1, e2) => string.CompareOrdinal(e1.name, e2.name)
);
FindEntity() Yes Static method for finding the first row which comply to the provided filter. The parameter is: Predicate<MyTable> filter : Filter to use for searching the row
    //find the first row, which gold more than 0
    MyTable entity = MyTable.FindEntity(entity => entity.gold > 0);
FindEntities() Yes Static method for finding all rows which comply to the provided filter. The parameters are:
  1. Predicate<MyTable> filter : Filter to use for searching the rows
  2. List<MyTable> result : Optional list to use as result (for decreasing garbage collection)
  3. Comparison<MyTable> sort : Optional sorter to sort the rows
    //find all rows, which gold more than 0
    List<MyTable> result= MyTable.FindEntities(entity => entity.gold > 0);
    //find all rows, which gold more than 0, entities are sorted by name
    List<MyTable> result= MyTable.FindEntities(
        entity => entity.gold > 0,
        null,
        (e1, e2) => string.CompareOrdinal(e1.name, e2.name)
    );
GetEntityByKey{key}(), GetEntitiesByKey{key}() Yes For each key static methods are generated for fast entity(s) lookups. GetEntitiesByKey method is generated only if a key is not unique.
    //Get the first entity which gold == 0. We assume key name="goldKey"
    MyTable entity = MyTable.GetEntityByKeygoldKey(0);
    //Get all entities with gold == 0. We assume key name="goldKey"
    List<MyTable> entities = MyTable.GetEntitiesByKeygoldKey(0);
FindEntitiesByIndex{indexName}() Yes For each index static methods are generated for fast entity(s) searches.
    //find all entities with "goldKey" between 0 inclusive and 10 exclusive.  We assume index name="goldIndex"
    MyTable.FindEntitiesByIndexgoldIndex(new BGIndexOperatorBetween<int>(0, 10, true, false));
Delete() No Use this method to delete the row. This method is not generated, but inherited from BGEntity class

    MyTable firstRow = MyTable.GetEntity(0);
    firstRow.Delete();
MetaDefault Yes Use this property to get access to the table (BGMetaEntity class)
    //get reference to meta (table)
    BGMetaEntity meta = MyTable.MetaDefault;
_{field_prefix}{FieldName} Yes Use this property to get access to the field (column) (BGField class)
    //get reference to name field
    BGFieldString nameField = MyTable._name;
    //get reference to gold field
    BGFieldInt goldField = MyTable._gold;
Related {MetaName} ListUsing {RelationName} Relation No For each incoming relation a property is generated for traversing relation in reverse direction.
    MyTable firstRow = MyTable.GetEntity(0);
    // we assume "OtherTable" table exists,
    // and it has "MyTable" relation, pointing to MyTable
    List<OtherTable> entitiesWhichPointToFirstRow = firstRow.RelatedOtherTableListUsingMyTableRelation
Load{field name}Async No For each Unity asset field, using Addressables loader, methods are generated for loading assets asynchronously
MyTable firstRow = MyTable.GetEntity(0);
//we assume "asset" Unity asset field exists with Addressables loader
firstRow.LoadAssetAsync(asset => {
    //make use of loaded asset
});
{entity name prefix}{entity name} Yes Optional static properties for each row, so you can access rows directly without need to get/search for it first. See Generate a property for each entity (optional) section below for more information
    //we assume first row's name="FirstRow" and entities prefix is "E_"
    MyTable firstRow = MyTable.E_FirstRow;
{tableName}{reference postfix} No Optional reference classes to reference database row/rows easily. See Reference classes section below for more information
public class Temp : MonoBehaviour
{
    // this is a reference to one single database row from "News" table
    // DB_ is a generated classes prefix and _Ref is reference classes postfix
    public DB_News_Ref newsRowReference;

    private void Start()
    {
        //to get access to the row- use Entity property
        DB_News row = newsRowReference.Entity;
        print(row);
    }
}

Views are also treated specially, read this blog post for more details.

Generate a property for each entity (optional)

Additionally, you can generate a C# property for each row(entity) and use this property to access the corresponding row directly, without the need to locate/find it first.

Requirements:

  • "Entities prefix" should be defined in CodeGen addon settings (for example KEY_). CodeGen addon settings is located here: BGDatabaseWindow->Addons->CodeGen
  • Each table, you want entities properties to be generated for, should have "Entity name is unique" toggle on under (Configuration->[TableName]) and "Entity name is empty" toggle off.
  • Each entity should have empty or unique name, containing letters, numbers, underscores, spaces and dots only. Entities with empty names will be skipped. Dots and spaces will be converted to underscores
  • Rows count (with not empty name) should be under 10000 rows

Once the properties are generated you can access particular row like so:

    BGE_MyTable entity = BGE_MyTable.KEY_MyUniqueKey;

where MyUniqueKey is the name of the row and KEY_ is entities prefix from CodeGen addon settings.

If this option is used, there are additional cases when you need to regenerate extension classes: if you add/delete the rows with names or if you change rows names.

Reference classes (optional)

Starting from version 1.6.10, reference classes can be generated optionally. These classes allow to reference database rows from your own scripts easily. To enable these classes generation - set "Reference class postfix" or "Reference list class postfix" parameters to some valid C# literals (for example _Ref and _ListRef). Two additional classes will be generated - one for referencing a single row and another for referencing multiple rows (from single table). If you use Odin inspector, version 3.1.7 has a bug and a wrong Editor drawer being shown in the Inspector - use [DrawWithUnity] attribute as a temporary workaround.

How to enable/disable

1) Open BGDatabase window from Unity menu Window->BGDatabase

2) Choose Addons->CodeGen

3) Toggle enabled on and fill all parameters:

  1. Code Generator - leave it as it is
  2. Source file - all generated classes will use one single .cs file. You can place it anywhere in your project, but not under Editor folder
  3. Package - package (namespace) for you classes.
  4. Classes names prefix - prefix for your classes names. For example, you can use prefix like D_ to distinct your database classes from the rest of the project classes
  5. Field names prefix - the same as classes names prefix, but for fields.
  6. Entities prefix (optional) - fill it if you want to generate a property for each entity (read more above)

After you fill all parameters, press Generate button to generate classes.

Note, you should regenerate these classes after any change to database structure (e.g. if you add/remove tables or fields, changing their names/order etc.)

Generated classes extensions

All generated classes are partial, so you can create your own class with the same namespace/name and add additional methods manually to these classes

What to read next:
  1. Code generation addon