9

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];
4

4 に答える 4

18

fmdb の一部である FMDatabaseQueue を使用してトランザクションを処理することもできます。

[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]];
}];

ドキュメンテーション

于 2013-01-26T23:01:41.847 に答える
16

最初の更新が失敗した場合、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
}
于 2011-07-05T09:44:55.210 に答える
1

ロールバックを実行する前に-lastErrorMessageandの値を出力することを追加して、正確に何がうまくいかなかったのかを理解できるようにすることは、有効な使用シナリオのように思えます。-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];
于 2011-07-05T09:14:03.677 に答える