2017-04-13 1 views
2

Ich habe als so eine Datenbank-Klasse erstellt:Transaktionen wird zum Einfügen werfen Fehler Sqlite.swift

class Database { 
    static let instance = Database() 
    private let categories = Table("Category") 
    private var db: Connection? 

    let cat_id = Expression<String>("id") 
    let cat_name = Expression<String>("name") 


    private init() { 
     let path = NSSearchPathForDirectoriesInDomains(
      .documentDirectory, .userDomainMask, true 
      ).first! 
     do { 
      db = try Connection("\(path)/SalesPresenterDatabase.sqlite3") 
      createTable() 
     } catch { 
      print("error") 
     } 
    } 
    func createTable() { 
     do{ 
      try self.db!.run(self.categories.create(ifNotExists: true) { table in 
       table.column(self.cat_id) 
       table.column(self.cat_name) 
      }) 
     }catch{ 
      print("error") 
     } 
    } 

    func addRow(table: DBTableNames, object: [Any]) -> Int64? { 
     do { 
     try self.db!.transaction() { 
      for obj in object{ 
       if table.rawValue == DBTableNames.Category.rawValue{ 
        let cats : CategoryObject = obj as! CategoryObject 
        let insert = self.categories.insert(self.cat_id <- cats.id, 
                 self.cat_name <- cats.name) 
        try self.db!.run(insert) 

       } 
      } 
      } 
     }catch{ 
      print("Insert failed \(error)") 
      return -1 
     } 
     return 1 
     } 
} 

ich dann mit dem folgenden eine Reihe hinzuzufügen gehen zu meinem Code aufrufen:

let returnValue = Database.instance.addRow(table: DBTableNames(rawValue: entity)!, 
               object: databaseObject) 

Das Problem, das ich habe ist, dass es immer einen Fehler wirft sagen:

einfügen konnte nicht abgeschlossen werden Der Vorgang ist fehlgeschlagen. (SQLite.Result Fehler 0) und voll: nicht Rollback - keine Transaktion aktiv (Code: 1)

Wenn ich sehe, diese Störung noch einmal mein Mac wird aus dem Fenster gehen!

Der gesamte Vorgang ist in einem Hintergrund-Thread, aber ich habe folgendes auch versucht:

DispatchQueue.main.async{ 
    let returnValue = Database.instance.addRow(table: DBTableNames(rawValue: entity)!, 
                object: databaseObject) 
} 

Es hat nicht funktioniert. Es macht keinen Sinn, da ich auch versucht habe, die Tabellen in einer Transaktion zu erstellen, und das hat perfekt funktioniert.

Jede Hilfe würde sehr geschätzt werden!

+0

Was passiert, wenn Sie dies auf dem Spielplatz ausführen? – rmon2852

+0

Ok Ich fange an zu glauben, dass dies ein Threading-Problem ist. Ich kann dies isoliert vom Rest des Codes arbeiten. Nun eine Sache, die ich nicht gesagt habe, ist, dass der Code von einem Alamofire-Vervollständigungsblock ausgeführt wird ... –

Antwort

0

Ihre Methoden func createTable() und func addRow() sind nicht Thread-sicher. Mehrere Threads können gleichzeitig darauf zugreifen.

Erstellen Sie eine private serielle DispatchQueue innerhalb Ihrer Singleton-Klasse und Funktionen über diese serielle Warteschlange. Dadurch wird verhindert, dass gleichzeitig von mehreren Threads auf die Datenbank zugegriffen wird, und die serielle Warteschlange wird gleichzeitige Aufgaben in die Warteschlange stellen.

+0

Ja, oder benutze eine SQLite-Bibliothek, die all den schwierigen Threading-Job für dich erledigt: https://github.com/groue/ GRDB.swift/blob/master/README.md # Nebenläufigkeit –

+0

Ich bin mir nicht sicher, ob Richard hier ein Threading-Problem hat. –