You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase(Unity) RTDB事务更新节点数据异常问题

Unity Firebase RTDB RunTransaction 节点覆盖问题

问题现象

使用RunTransaction更新RTDB节点时,预期新增key_a/key_b/key_c并保留原有key_d,但真机测试中节点被完全覆盖,key_d丢失。编辑器测试和RTDB规则playground中表现符合预期(新键添加、旧键保留)。

安全规则设置了.validate": "newData.hasChildren(['key_a', 'key_b', 'key_c', 'key_d'])",该规则在编辑器中有效,但真机上无法阻止不符合要求的数据写入。

代码片段

初始更新代码:

Dictionary<string, object> newData = new Dictionary<string, object>();
newData["key_a"] = "val_a";
newData["key_b"] = "val_b";
newData["key_c"] = "val_c";
mutableData.Value = newData;

完整交易代码:

db_reference
.Child("node")
.RunTransaction(RunTransaction)
.ContinueWithOnMainThread(task => {
    if (task.Exception != null) {
        Debug.Log("Transaction exception.");
    } else if (task.IsCompleted) {
        Debug.Log("Transaction complete.");
    }
});

TransactionResult RunTransaction(MutableData mutableData) {
List<object> data = mutableData.Value as List<object>;
 if (data != null) {
   Dictionary<string, object> newData = new Dictionary<string, object>();
   newData["key_a"] = "val_a";
   newData["key_b"] = "val_b";
   newData["key_c"] = "val_c";
   mutableData.Value = newData; // 节点被覆盖的核心问题点
 } else {
   Dictionary<string, object> newData = new Dictionary<string, object>();
   newData["key_a"] = "val_a";
   newData["key_b"] = "val_b";
   newData["key_c"] = "val_c";
   newData["key_d"] = "val_d";
   mutableData.Value = newData;
 }
 return TransactionResult.Success(mutableData);
}

环境信息

  • Unity: 2021.3.9f1
  • Firebase: 9.4.0

问题原因

  1. 类型转换错误:代码中错误地将mutableData.Value转为List<object>,但RTDB的对象节点实际存储为Dictionary<string, object>。不同平台(编辑器/真机)的SDK解析行为不一致,导致真机上进入错误分支,直接写入不含key_d的新字典。
  2. 节点完全覆盖:直接将mutableData.Value赋值为全新的Dictionary,会替换整个节点数据,而非在原有数据基础上更新。

解决方案

修改RunTransaction方法,正确获取原有节点数据并进行增量更新:

TransactionResult RunTransaction(MutableData mutableData) {
    // 正确解析原有节点数据为Dictionary
    Dictionary<string, object> existingData = mutableData.Value as Dictionary<string, object>;
    Dictionary<string, object> newData;

    if (existingData != null) {
        // 基于原有数据创建新字典,保留所有旧键值
        newData = new Dictionary<string, object>(existingData);
    } else {
        // 节点不存在时初始化完整数据
        newData = new Dictionary<string, object>();
        newData["key_d"] = "val_d";
    }

    // 增量更新需要修改的键
    newData["key_a"] = "val_a";
    newData["key_b"] = "val_b";
    newData["key_c"] = "val_c";

    mutableData.Value = newData;
    return TransactionResult.Success(mutableData);
}

说明

  • 该修改会保留原有节点的所有键值,仅更新指定的key_a/key_b/key_c,确保key_d不会丢失。
  • 修正类型转换后,编辑器和真机的行为将保持一致,安全规则也会正常验证newData包含所有要求的子节点。

内容的提问来源于stack exchange,提问作者FDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:50:24