dart 锁定firebase firestore收集和写入数据+ flutter

jgzswidk  于 2024-01-04  发布在  Flutter
关注(0)|答案(1)|浏览(258)

我有一个这样的场景
当用户尝试更新集合中的字段“sample”时:

  • 我有一个检查,看看该字段是否为空。
  • 当该字段为空时,更新该字段并显示更新成功的吐司消息
  • 当该字段不为空时,仅显示更新失败的吐司消息

我面临的问题是
当两个用户同时更新字段时(仅毫秒差异):

  • 用户1收到成功消息
  • 用户2也会收到成功消息
  • 但是只有用户2的数据被更新

我认为这个问题是因为时差很小。可能是:

  • 当用户1检查该字段时-其为空
  • 当用户2检查该字段时-它也是空的
  • 用户1更新值
  • 用户2还更新覆盖用户1的值的值

当用户1检查字段并进行更新时,是否有方法锁定字段的更新,以便用户2无法更新同一字段中的值
在这里我添加了示例代码:

  1. if (ownerId.isEmpty && equipmentId.isEmpty) {
  2. dm
  3. .assignBooking(
  4. bid: bid,
  5. status: 'approved',
  6. ownerId: uid,
  7. equipmentid: eid!,
  8. model: model,
  9. bookingType: notificationBookingType)
  10. .then((value) {
  11. if (value == true) {
  12. Fluttertoast.showToast(
  13. msg: AppLocalizations.of(context)!
  14. .bookingsuccessfullyApproved,
  15. timeInSecForIosWeb: 5);
  16. } else {
  17. Fluttertoast.showToast(
  18. msg: AppLocalizations.of(context)!
  19. .bookingAcceptedBysomeoneElse,
  20. timeInSecForIosWeb: 5);
  21. }
  22. Future<bool> assignBooking({
  23. required String bid,
  24. required String status,
  25. required String ownerId,
  26. required String equipmentid,
  27. required String model,
  28. required String bookingType,
  29. }) async {
  30. // Fetch the existing booking data
  31. var bookingData = await allBookings.doc(bid).get();
  32. // Check if assigned_equipment_owner_id is empty
  33. if (bookingData['assigned_equipment_owner_id'] == null ||
  34. bookingData['assigned_equipment_owner_id'].isEmpty) {
  35. // Update only if assigned_equipment_owner_id is empty
  36. await allBookings.doc(bid).update({
  37. "status": status,
  38. 'assigned_equipment_owner_id': ownerId,
  39. 'equipment_id': equipmentid,
  40. 'model': model,
  41. 'booking_type': bookingType,
  42. });
  43. return true;
  44. } else {
  45. return false;
  46. }
  47. }

字符串
在更新和显示吐司消息之前,我正在检查所有者ID和设备ID是否在两个地方为空。但我仍然无法处理这个问题

lstz6jyr

lstz6jyr1#

您面临的问题与竞争条件有关,其中两个用户同时检查条件(assigned_equipment_owner_id为空),并且他们都发现它为空。因此,两个用户都继续更新数据,导致都收到成功消息,但实际上只有一个更新反映在数据库中。
要处理这种情况,您需要实现一种机制来确保更新操作中的原子性,这样每次只有一个用户可以成功地更新数据。
一种方法是使用事务来确保检查和更新操作被视为单个原子单元。这有助于避免多个用户可能试图同时更新数据的竞争条件。

  1. Future<bool> assignBooking({
  2. required String bid,
  3. required String status,
  4. required String ownerId,
  5. required String equipmentid,
  6. required String model,
  7. required String bookingType,
  8. }) async {
  9. try {
  10. await FirebaseFirestore.instance.runTransaction((transaction) async {
  11. var bookingData = await allBookings.doc(bid).get();
  12. if (bookingData['assigned_equipment_owner_id'] == null ||
  13. bookingData['assigned_equipment_owner_id'].isEmpty) {
  14. transaction.update(allBookings.doc(bid), {
  15. "status": status,
  16. 'assigned_equipment_owner_id': ownerId,
  17. 'equipment_id': equipmentid,
  18. 'model': model,
  19. 'booking_type': bookingType,
  20. });
  21. } else {
  22. throw 'Equipment is already assigned to another owner.';
  23. }
  24. });
  25. return true;
  26. } catch (e) {
  27. return false;
  28. }
  29. }

字符串

展开查看全部

相关问题