Database
1. Overview
The database is a system that provides real-time data processing and synchronization. It automatically processes and synchronizes related data through reference relationships.
2. Key Features
- Real-time data synchronization
- Automatic data processing through references
- Asynchronous task handling
- Distributed processing support
3. Data Model Design
// Character model
[Table("Characters")]
public class Character : BaseModel
{
[PrimaryKey("Id")]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Level")]
public int Level { get; set; }
[Reference(typeof(Inventory))] // Inventory reference settings
public List<Inventory> Items { get; set; }
}
// Inventory model
[Table("Inventory")]
public class Inventory : BaseModel
{
[PrimaryKey("Id")]
public int Id { get; set; }
[Column("CharacterId")]
public int CharacterId { get; set; }
[Column("ItemId")]
public int ItemId { get; set; }
[Column("Slot")]
public int Slot { get; set; }
[Column("Amount")]
public int Amount { get; set; }
}
4. Basic Use
Client Initialization
public class GameManager : MonoBehaviour
{
private BACKND.Database.Client _client;
void Start()
{
_client = new BACKND.Database.Client();
}
}
Creating Data
private IEnumerator CreateCharacter(string name)
{
var character = new Character
{
Name = name,
Level = 1,
Items = new List<Inventory>() // Start with an empty inventory
};
yield return _client.From<Character>().Insert(character);
}
Lookup Data
private IEnumerator GetCharacter(int characterId)
{
var op = _client.From<Character>()
.Include(x => x.Items) // Load inventory as well
.Where(x => x.Id == characterId)
.First();
yield return op;
var character = op.Current as Character;
if (character != null)
{
Debug.Log($"Character: {character.Name}, Number of items: {character.Items.Count}");
}
}
5. Inventory System Example
Inventory Manager
public class InventoryManager : MonoBehaviour
{
private BACKND.Database.Client _client;
// Add item
private IEnumerator AddItem(int characterId, int itemId, int amount, int slot)
{
var op = _client.From<Character>()
.Include(x => x.Items)
.Where(x => x.Id == characterId)
.First();
yield return op;
var character = op.Current as Character;
if (character != null)
{
// Add new items in character's inventory
character.Items.Add(new Inventory
{
CharacterId = characterId,
ItemId = itemId,
Amount = amount,
Slot = slot
});
// Inventory is automatically processed upon updating character
yield return _client.From<Character>()
.Where(x => x.Id == characterId)
.Update(character);
}
}
// Move item
private IEnumerator MoveItem(int characterId, int fromSlot, int toSlot)
{
var op = _client.From<Character>()
.Include(x => x.Items)
.Where(x => x.Id == characterId)
.First();
yield return op;
var character = op.Current as Character;
if (character != null)
{
var items = character.Items;
var fromItem = items.FirstOrDefault(x => x.Slot == fromSlot);
var toItem = items.FirstOrDefault(x => x.Slot == toSlot);
if (fromItem != null)
{
fromItem.Slot = toSlot;
if (toItem != null)
{
toItem.Slot = fromSlot;
}
// Modified slot info is also automatically saved upon updating character
yield return _client.From<Character>()
.Where(x => x.Id == characterId)
.Update(character);
}
}
}
// Remove item
private IEnumerator RemoveItem(int characterId, int slot)
{
var op = _client.From<Character>()
.Include(x => x.Items)
.Where(x => x.Id == characterId)
.First();
yield return op;
var character = op.Current as Character;
if (character != null)
{
// Remove item in the slot
character.Items.RemoveAll(x => x.Slot == slot);
// Item deletion automaticalled processed upon character update
yield return _client.From<Character>()
.Where(x => x.Id == characterId)
.Update(character);
}
}
}
6. Precautions and Tips
Workflow
// Good Example: Modify data in memory and update all at once
character.Items.Add(newItem);
yield return _client.From<Character>().Update(character);
// Bad Example: Unnecessary DB operations
yield return _client.From<Inventory>().Insert(newItem); // Unnecessary
yield return _client.From<Character>().Update(character);
Using Include
// Good Example: Load everything at once using Include
var op = _client.From<Character>()
.Include(x => x.Items)
.First();
// Bad Example: Multiple queries
var charOp = _client.From<Character>().First();
var itemsOp = _client.From<Inventory>().Where(...);
null Checks
// Always perform a null check
if (character?.Items != null)
{
// Process safely
}
Key Points
- If there is a reference relationship, when the parent object is updated, the child objects are also automatically handled.
- Modify data in memory and save it with a single update.
- Actively use Include to reduce the number of queries.
- Always handle DB operations with yield return. :::