使用Unity3d在Firebase中存储DateTime值的最佳做法

时间:2017-07-05 21:29:29

标签: c# datetime firebase unity3d firebase-realtime-database

我正在建立一个Unity3d 2D游戏,我使用Firebase作为数据库。我需要在数据库中存储相当多的DateTime值(以UTC为单位),并且我想知道这样做的最佳实践是什么。

DateTime字段主要用于排序/过滤。

根据Firebase文档,我应该使用Firebase.Database.ServerValues.TIMESTAMP只是object

事情是,我在我的Unity游戏中使用强类型模型,如下所示:

[Serializable]
public class Profile {

    [NonSerialized]
    public string ProfileKey;

    // Serializable attributes
    public string userId;
    public string name;
    public int age;
    public string gender; // "M" or "F"
    public DateTime utcCreated; // UTC   
    public DateTime utcUpdated; // UTC
}   

当我使用Unity Profile方法保存/更新JsonUtility.ToJson()时,就像这样:

var profiles = db.Child ("profiles");

Profile profile = new Profile {
    userId = GameManager.Instance.User.UserId,
    name = "My new profile",
    age = 23,
    gender = "M",
    utcCreated = ?? // Should somehow use Firebase.Database.ServerValues.TIMESTAMP here, I guess?
};              

string json = JsonUtility.ToJson (profile);     

var profileKey = profiles.Push ().Key;

profiles.Child (profileKey).SetRawJsonValueAsync (json, 1).ContinueWith (t => {
    // .. handle response here
});

我不确定我应该在我的模型上设置utcCreated字段到底是什么。试图简单地将字段设为object,但没有将值插入Firebase。还尝试将其设为.ToString() Firebase.Database.ServerValues.TIMESTAMP对象的字符串,但Firebase中未插入任何值。

有谁知道如何做到这一点? ;-)或者只是关于在Firebase中存储日期和时间戳的最佳实践的任何帮助/提示?

提前致谢。

1 个答案:

答案 0 :(得分:4)

好吧,对于有这个问题的其他人,他们不想花费数小时的挫折感,答案是:你不能(也许不应该,猜测它是有原因的)设置{{1}模型/对象上的对象。

ServerValue.Timestamp是您在Firebase文档中专门设置的内容,可以致电ServerValue.TimestampSetValueAsync()

所以我做的是在我的UpdateChildrenAsync()类中添加两个字段:一个表示unix时间戳服务器值,另一个表示作为C#Profile对象的unix时间戳服务器值:< / p>

DateTime

using System; using System.Collections.Generic; using System.Linq; [Serializable] public class Profile { [NonSerialized] public string profileKey; [NonSerialized] public long utcCreatedTimestamp; [NonSerialized] public DateTime utcCreated; // Serializable attributes public string userId; public string name; public int age; public string gender; // "M" or "F" public Profile() { } public Profile(Dictionary<string, object> fromFirebaseResult) { userId = fromFirebaseResult.ContainsKey("userId") ? fromFirebaseResult.First(x => x.Key == "userId").Value.ToString() : string.Empty; name = fromFirebaseResult.ContainsKey("name") ? fromFirebaseResult.First(x => x.Key == "name").Value.ToString() : string.Empty; age = fromFirebaseResult.ContainsKey("age") ? int.Parse(fromFirebaseResult.First(x => x.Key == "age").Value.ToString()) : 0; gender = fromFirebaseResult.ContainsKey("gender") ? fromFirebaseResult.First(x => x.Key == "gender").Value.ToString() : string.Empty; if (fromFirebaseResult.ContainsKey("utcCreatedUnix")) { long milliseconds; if(long.TryParse(fromFirebaseResult.First(x => x.Key == "utcCreatedUnix").Value.ToString(), out milliseconds)) { utcCreatedTimestamp = milliseconds; DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); utcCreated = epoch.AddMilliseconds(milliseconds); } } } } 类有一个默认构造函数和一个构造函数,它需要Profile,因为这是我们从Unity查询时从Firebase获得的内容。

将新的Dictionary<string, object>保存到Firebase时,我会创建一个新的Profile对象,而不会设置与日期和时间相关的任何内容。将其保存在Firebase中,然后调用Profile设置Firebase中的UpdateChildrenAsync字段。像这样:

utcCreatedUnix

从Firebase获取DatabaseReference db = FirebaseDatabase.DefaultInstance.RootReference; // Get the user id string userId = GameManager.Instance.User.UserId; // Get a reference to the profiles var profiles = db.Child("profiles"); // Create a new serializable profile Profile profile = new Profile { userId = userId, name = "Bo Mortensen", age = 34, gender = "M" }; // Serialize profile to JSON string json = JsonUtility.ToJson (profile); // Push a new document to the database var profileKey = profiles.Push ().Key; // Set JSON for this document profiles.Child (profileKey).SetRawJsonValueAsync (json, 1).ContinueWith (t => { if (t.IsCompleted) { // Assign the profile key (unique key generated by Firebase) to the profile profile.profileKey = profileKey; // Set the Firebase server timestamp on the datetime object profiles.Child(profileKey).UpdateChildrenAsync(new Dictionary<string, object> { { "utcCreatedUnix", ServerValue.Timestamp } }); } }); 文档时,我现在可以:

Profile

您可能会问为什么我不只是存储var db = FirebaseDatabase.DefaultInstance.RootReference; var profileRef = db.Child("profiles/MyProfileKey"); profileRef.GetValueAsync().ContinueWith(t => { var values = t.Result.Value as System.Collections.Generic.Dictionary<string, object>; // Let the constructor populate the fields Profile profile = new Profile(values) { profileKey = profileRef.Key }; DateTime createdDate = profile.utcCreated; }); 我可以做到这一点,但我不想依赖客户端时钟设置。通过使用Firebases ServerValue.Timestamp,Firebase可以使用该应用确定正确的时间而不是单个客户端。

希望这对其他任何人都有帮助: - )