【问题标题】:iOS SQLite FMDB Transactions.. Correct usage?iOS SQLite FMDB 事务.. 正确用法?
【发布时间】:2011-09-28 15:28:49
【问题描述】:

我将尝试使用带有 FMDB SQLite iOS 包装器的事务。

文档对交易有点模糊,但通过快速浏览一些功能,我得出了以下逻辑:

[fmdb beginTransaction];
    // Run the following query
    BOOL res1 = [fmdb executeUpdate:@"query1"];
    BOOL res2 = [fmdb executeUpdate:@"query2"];

if(!res1 || !res2) [fmdb rollback];
else [fmdb commit];

【问题讨论】:

    标签: objective-c ios sqlite fmdb


    【解决方案1】:

    这似乎是一个有效的使用场景,我可能会在执行回滚之前添加输出 -lastErrorMessage-lastErrorCode 的值,以便您了解到底出了什么问题。

    更好的是,在每个 -executeUpdate 之后进行这些调用,这样您就会知道每个语句之后是否发生错误:

    [fmdb beginTransaction];
    
    // Run the following query
    BOOL res1 = [fmdb executeUpdate:@"query1"];
    if (!res1) {
       NSLog(@"Error %d - %@", [fmdb lastErrorMessage], [fmdb lastErrorCode]);
    }
    
    BOOL res2 = [fmdb executeUpdate:@"query2"];
    if (!res2) {
       NSLog(@"Error %d - %@", [fmdb lastErrorMessage], [fmdb lastErrorCode]);
    }
    
    if(!res1 || !res2) [fmdb rollback];
    else [fmdb commit];
    

    【讨论】:

      【解决方案2】:

      如果第一次失败,我不会尝试进行第二次更新。

      bool ret = false;
      [fmdb beginTransaction];
      ret = [fmdb executeUpdate:@"query1"];
      if (ret)
      {
          ret = [fmdb executeUpdate:@"query2"];
          if (!ret)
          {
               // report error 2
          }
      }
      
      if(ret) 
      {
          if (![fmdb commit])
          {
              // panic!
          }
      }
      else
      {
          if (![fmdb rollback])
          {
              // panic!
          }
      }
      

      对于偏执的鲁棒性,你应该有一个 try ... catch 块,以防任何东西引发异常。如果你这样做,你可以利用它来发挥你的优势。

      [fmdb beginTransaction];
      @try
      {
          if (![fmdb executeUpdate:@"query1"])
          {
              // report error
              @throw someExcpetion;
          }
          if (![fmdb executeUpdate:@"query2"])
          {
              // report error
              @throw someExcpetion;
          }
          [fmdb commit]
      }
      @catch(NSException* e)
      {
          [fmdb rollback];
          // rethrow if not one of the two exceptions above
      }
      

      【讨论】:

        【解决方案3】:

        您还可以使用 FMDatabaseQueue 来处理您的事务,它是 fmdb 的一部分:

        [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
        
            if (whoopsSomethingWrongHappened) {
                *rollback = YES;
                return;
            }
            // etc…
            [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
        }];
        

        Documentation

        【讨论】:

        • inTransaction 帮了大忙。谢谢老兄。
        • 没有人提到whoopsSomethingWrongHappened 来自哪里...
        • 这有一个缺点。您无法控制 beginTransaction 和 commit 方法。他们的返回值。如果 beginTransacion(在 inTransaction 中使用)返回 false 怎么办?你无法控制它
        【解决方案4】:

        快捷方式:

        let queue = FMDatabaseQueue(path: databaseURL.path!)
        
        queue.inTransaction() {
            db, rollback in
        
            result = db.executeUpdate("INSERT INTO client VALUES (NULL, ?)", client.name ?? "")
        
            if result {
                client.ID = Int(db.lastInsertRowId())
            } else {
                rollback.initialize(true)
                print("\(__FUNCTION__) insert into table failed: \(db.lastErrorMessage())")
            }
        }
        
        queue.close()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-05
          • 1970-01-01
          • 1970-01-01
          • 2012-02-24
          • 1970-01-01
          相关资源
          最近更新 更多