How to retrieve a single record from Firebase Real Time Database in Xamarin-Android?

拈花ヽ惹草 提交于 2020-06-01 05:47:04

问题


I need to read only one entity from Firebase Realtime Database and convert the result into a C# class matching the structure, but I haven't found a solution clear. Having this tree:

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

And this C# class:

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

I would like to retrieve only one record by email, which I know and it is unique. But, if I do include the NuGet package Xamarin.Firebase.Database there not exists a method or extension method such as OnceSingle<T>() or OnceSingleAsync<T>() in it:

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.

In the other hand, by including package Xamarin.Forms.FirebaseWrapper, an upgrade of the former Firebase.Xamarin, that supports OnceSingleAsync<T>() one can code something like this:

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...

But it doesn't work. It raises a System.AggregateException: 'One or more errors occurred. (Response status code does not indicate success: 400 (Bad Request).)'

The following is the only I've managed to make it work, but it is under performant because it retrieves all the collection and performs the search locally.

    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
            }

Any ideas that can help to clarify my mind to do it simpler and better will be appreciated.


回答1:


I would like to retrieve only one record by email, which I know and it is unique.

What you are looking for is a way to query the database based on certain value(Email). Reading through the Firebase Database Doc, you can find the Filtering Data which explains what you want.

To meet your scenario, what you need to do is:

  1. Sort your children elements based on Email and use EuqalTo() to limit the output data range.

    var db = FirebaseDatabase.Instance;
    var mDatabase = db.GetReference("characters");
    Query query = mDatabase.OrderByChild("Email")
                           .EqualTo("harry.potter@example.com");
    
  2. Create a Child event listener to retrieve the filtered data.

    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. Register 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();
    }

//Hope this helps



来源:https://stackoverflow.com/questions/58881101/how-to-retrieve-a-single-record-from-firebase-real-time-database-in-xamarin-andr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!