Flutter Firebase multiple setData threads only responds to last thread

200

Try the following:

 await Firestore.instance.collection('stores').document(user.uid).setData({'String1': 'My First String', 'String2': 'My Second String', 'String3': 'My Third String'});
 await Firestore.instance.collection('stores').document(user.uid).updateData({'String4': 'My Fourth String', 'String5': 'My Fifth String', 'String6': 'My Sixth String'});

Use setData() for the first write to add the data, and in the second write use updateData() to add the new fields, currently the second setData() is overriding the fields in the first setData() that's why you dont see String1, String2,String3 in the database.

Share:
200
Bisclavret
Author by

Bisclavret

Updated on November 28, 2022

Comments

  • Bisclavret
    Bisclavret over 1 year

    When using multiple setData threads to write to a Firebase database, only the last thread is resolved. For example:

    Future registerWithEmailAndPassword(String email, String password) async {
        try {
          AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
          FirebaseUser user = result.user;
          await Firestore.instance.collection('stores').document(user.uid).setData({'String1': 'My First String', 'String2': 'My Second String', 'String3': 'My Third String'});
          await Firestore.instance.collection('stores').document(user.uid).setData({'String4': 'My Fourth String', 'String5': 'My Fifth String', 'String6': 'My Sixth String'});
          return userFromFirebaseUser(user);
    
        } catch(e) {
          print('REGISTER EnP ERROR: ' + e.toString());
          return null;
        }
      }
    

    Results in the Firebase database showing the following when I create a new user:

    String4: "My Fourth String"
    String5: "My Fifth String"
    String6: "My Sixth String"
    

    Going to need to be able to write to the database like this, each write should "await" completion before moving on, but this does not seem to be what happens.

    (EDIT) For barbecu:

    Actual code is that instead of writing directly with setData I pass data through classes. So instead of:

    await Firestore.instance.collection('stores').document(user.uid).setData({'String1': 'My First String', 'String2': 'My Second String', 'String3': 'My Third String'});
    await Firestore.instance.collection('stores').document(user.uid).setData({'String4': 'My Fourth String', 'String5': 'My Fifth String', 'String6': 'My Sixth String'});
    

    It is actually written like:

    await DatabaseService1(uid: user.uid).updateUserData(variable1, variable2, variable3);
    await DatabaseService2(uid: user.uid).updateUserData(variable4, variable5, variable6);
    

    So when it comes to a batch type solution, I am not quite sure how to write the syntax for how to call these classes into the batch and then run it.

    • Frank van Puffelen
      Frank van Puffelen almost 4 years
      Please update your question to show what updateUserData does.
    • Bisclavret
      Bisclavret almost 4 years
      Hi Frank, I have added the code as requested. It all works perfectly fine in populating data to my database, unless I run another thread. And OHDatabaseService is exactly the same.
    • Frank van Puffelen
      Frank van Puffelen almost 4 years
      Thanks for that update. I don't immediately see what's going wrong here. If you simplify the code to not use the DatabaseService class anymore, but instead call setData() directly from within registerWithEmailAndPassword, can you still reproduce the problem?
    • Bisclavret
      Bisclavret almost 4 years
      Thank you so much for following up, Frank. I followed your suggestion and just used setData directly. Of the two lines added, it only processed the second line again. Just ignores the first line completely. I'll add the tested code to the question.
    • barbecu
      barbecu almost 4 years
      Not really sure what the problem is, But why not use Batch writes instead (Or transactions if you need to read data too) ? That way you can update the data atomically and ensure both operations occurred.
    • Bisclavret
      Bisclavret almost 4 years
      The problem is, barbecu, that if I ask the application to write 6 strings to the database that it should then write 6 strings to the database. Not 3. I am reading about batches now actually, but not sure on exactly how to write this. The above code is oversimplified to illustrate the issue, but I essentially have two separate classes that each write to the database, and I want to be able to run both classes. I can add this code back in to show you if it will help.
  • Peter Haddad
    Peter Haddad almost 4 years
    @barbecu yes that's true
  • Bisclavret
    Bisclavret almost 4 years
    Yeah, this appears to be the issue! Thanks so much Peter. I have changed the second class to use "updateData" instead of "setData" inside the class. I am just testing now if I can use this class later in the app with it in this state.
  • Peter Haddad
    Peter Haddad almost 4 years
    @Bisclavret no problem yes first you need to use setData then u have to use either updateData or setData with merge true to add new fields without overriding
  • Frank van Puffelen
    Frank van Puffelen almost 4 years
    Great catch Peter!
  • Bisclavret
    Bisclavret almost 4 years
    Ok, so I got a chance to test it last night, and I was able to use the DatabaseService2 class, with updateData whenever I wanted to call it. So I will accept this answer as it doesn't break anything ;) Thank you so much!