Flutter Firebase multiple setData threads only responds to last thread
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.
Bisclavret
Updated on November 28, 2022Comments
-
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 almost 4 yearsPlease update your question to show what
updateUserData
does. -
Bisclavret almost 4 yearsHi 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 almost 4 yearsThanks 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 callsetData()
directly from withinregisterWithEmailAndPassword
, can you still reproduce the problem? -
Bisclavret almost 4 yearsThank 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 almost 4 yearsNot 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 almost 4 yearsThe 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 almost 4 years@barbecu yes that's true
-
Bisclavret almost 4 yearsYeah, 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 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 almost 4 yearsGreat catch Peter!
-
Bisclavret almost 4 yearsOk, 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!