【问题标题】:How to retrieve a single record from Firebase Real Time Database in Xamarin-Android?如何从 Xamarin-Android 中的 Firebase 实时数据库中检索单个记录?
【发布时间】:2020-05-17 05:54:40
【问题描述】:

我只需要从 Firebase 实时数据库中读取一个实体并将结果转换为与结构匹配的 C# 类,但我还没有找到明确的解决方案。拥有这棵树:

{
 "characters" : {
    "c1" : {
      "Email" : "peter.pan@example.com",
      "LastName" : "Pan",
      "Name" : "Peter"
    },
    "c2" : {
      "Email" : "harry.potter@example.com",
      "LastName" : "Potter",
      "Name" : "Harry"
    }
  }
}

还有这个 C# 类:

public class Character 
{
   public string Email {get; set; }
   public string Name { get; set; }
   public string LastName { get; set; }
}

我只想通过电子邮件检索一条记录,我知道这是唯一的。但是,如果我确实包含 NuGet 包 Xamarin.Firebase.Database,则其中不存在诸如 OnceSingle<T>() or OnceSingleAsync<T>() 之类的方法或扩展方法:

Character character = await FirebaseDatabase.Instance
  .GetReference(CharactersRoot)
  .OrderByChild("Email")
  .EqualTo("harry.potter@example.com") //Works until here
  .OnceSingleAsync<Character>(); //THIS METHOD IS NOT AVAILABLE. It doesn't work.

另一方面,通过包含包Xamarin.Forms.FirebaseWrapper,升级前Firebase.Xamarin,支持OnceSingleAsync&lt;T&gt;(),可以编写如下代码:

FirebaseClient fbClient= new FirebaseClient(Root);
var task = Task<Character>.Run(async () => 
            {
                return await fbClient.Child(CharactersRoot)
                    .OrderBy("Email")
                    .EqualTo("harry.potter@example.com")
                    .OnceSingleAsync<Character>().ConfigureAwait(false)
            });                 
            var character = task.Result;
            // do something with character...

但它不起作用。它引发 System.AggregateException: '一个或多个错误发生。 (响应状态码不表示成功:400(错误请求)。)'

以下是我设法使它工作的唯一方法,但它性能不佳,因为它检索所有集合并在本地执行搜索。

    FirebaseClient fbClient= new FirebaseClient(Root);
    var task = Task<Character>.Run(async () =>
            {
                return await fbClient.Child(CharactersRoot)                                     
                                    .OnceAsync<Character>()
                                    .ConfigureAwait(false);
            });
            var character = task.Result
                            .Where(item => item.Object.Email == "harry.potter@example.com")
                            .Select(itm => itm.Object)
                            .FirstOrDefault();
            if (character != null)
            {
                //Do something with character
            }

任何可以帮助我理清思路以使其更简单、更好的想法将不胜感激。

【问题讨论】:

  • 没人知道吗?我说的不够清楚? O 只有我一个人尝试使用 Xamarin 进行开发吗?请告诉我...

标签: c# performance xamarin firebase-realtime-database xamarin.forms


【解决方案1】:

我只想通过电子邮件检索一条记录,我知道这是唯一的。

您正在寻找的是一种基于特定值(电子邮件)查询数据库的方法。 通读 Firebase 数据库文档,您可以找到 Filtering Data,它解释了您想要什么。

为了满足你的场景,你需要做的是:

  1. 根据 Email 对子元素进行排序,并使用 EuqalTo() 限制输出数据范围。

    var db = FirebaseDatabase.Instance;
    var mDatabase = db.GetReference("characters");
    Query query = mDatabase.OrderByChild("Email")
                           .EqualTo("harry.potter@example.com");
    
  2. 创建一个子事件监听器来检索过滤后的数据。

    public class MyChildEventListener : Java.Lang.Object, IChildEventListener
    {
        public void OnCancelled(DatabaseError error)
        {}
    
        public void OnChildAdded(DataSnapshot snapshot, string previousChildName)
        {
            //this method will be triggered
            //snapshot's key is c2 namly harry potter
        }
    
        public void OnChildChanged(DataSnapshot snapshot, string previousChildName)
        {}
    
        public void OnChildMoved(DataSnapshot snapshot, string previousChildName)
        {}
    
        public void OnChildRemoved(DataSnapshot snapshot)
        {}
    }
    
  3. 注册MyChildEventListener:

    query.AddChildEventListener(new MyChildEventListener());
    

【讨论】:

    【解决方案2】:
    public async Task<Character> GetAttendant(string email)
        {
            return (await firebase
              .Child("Character")
              .OnceAsync<Character>()).Select(item => new Character
              {
                  EmailAddress = email,
              }).FirstOrDefault();
        }
    

    //希望对你有帮助

    【讨论】:

    • 欢迎来到 Stack Overflow。没有任何解释的代码转储很少有帮助。 Stack Overflow 是关于学习的,而不是提供 sn-ps 来盲目复制和粘贴。请edit您的问题并解释它如何比OP提供的更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多