3
votes

Hi I am trying to implement simple transaction using Firebase Firestore in Flutter. The process is simple just update two documents like this:

DocumentSnapshot productSnapshot = await productReference.get();
    DocumentSnapshot userSnapshot = await userReference.get();
    DocumentSnapshot userProductSnapshot = await userProductReference.get();
    if (productSnapshot.exists &&
        userSnapshot.exists &&
        userProductSnapshot.exists) {
      double price = double.parse(productSnapshot.data["productPrice"].toString());
      double money = double.parse(userSnapshot.data["money"].toString());
      double afterBuyMoney = money - price;
      if (afterBuyMoney >= 0) {
        await userReference.updateData({"money": afterBuyMoney});
        await userProductReference.updateData(({"isOwned": true}));
        response = "success";
      }
    }

This codes already works fine and get the expected result also data is updated in cloud database, however because there is two transaction and it is possible there is error in middle transaction. I want to implement this using Firestore runTransaction so if there is error, all the transaction will be rollbacked.

This is my codes using Firestore runTransaction

await Firestore.instance.runTransaction((transaction) async {
      DocumentSnapshot productSnapshot = await transaction.get(productReference);
      DocumentSnapshot userSnapshot = await transaction.get(userReference);
      DocumentSnapshot userProductSnapshot = await transaction.get(userProductReference);
      if(productSnapshot.exists && userSnapshot.exists && userProductSnapshot.exists) {
        double price = double.parse(productSnapshot.data["productPrice"].toString());
        double money = double.parse(userSnapshot.data["money"].toString());
        double afterBuyMoney = money - price;
        if (afterBuyMoney >= 0) {
          await transaction.update(userReference, {"money": afterBuyMoney});
          await transaction.update(userProductReference,({"isOwned": true}));
          response = "success";
        }
      }
    }).then((_) {
      print("Success");
    }).catchError((error) {
      response = error.message;
    });

This codes is also works fine and print the "Success", however in the firestore database the data is not updated and it seems the transaction doesn't work although there is no error in log. Is there any missing step or wrong in my code? How to fix this?

2

2 Answers

6
votes

Try:

Future<bool> insert() async {
    String document = "document";
    String collection = "collection";
    Map map = new Map();
    map["last_name"] = "Last Name";
    map["first_name"] = "First Name";
    map["middle_name"] = "Middle Name";

    DocumentReference documentReference = Firestore.instance.collection(collection).document(document);
    Firestore.instance.runTransaction((transaction) async {
      await transaction
          .set(documentReference, {
            'last_name': map['last_name'],
            'first_name': map['first_name'],
            'middle_name': map['middle_name']
          })
          .catchError((e) {})
          .whenComplete(() {});
    }).catchError((e) {
      return false;
    });

    return true;
}
0
votes

I provided a possible solution HERE which was to switch the version of Flutter you are using.