如何在GRDB中的只读数据库连接中调用新的数据库连接?

时间:2019-07-08 23:52:08

标签: swift grdb

下面的函数返回一个n记录。在大多数情况下,它将在可选的Ledgers变量中找到它,或者通过搜索数据库来找到它,在那里不需要写。我想使用只读GRDB数据库连接。只读数据库连接可以在不同的线程上并行运行。

在极少数情况下,前两个步骤失败,我可以创建一个默认的分类帐。调用_currentReceipt将引发致命错误,数据库连接不可重入。我正在寻找一种方法来保存默认分类帐,而不必将整个功能包装在读写连接中。

我可以在GRDB .read块内的单独队列上调用NSOperation吗?

try FoodyDataStack.thisDataStack.dbPool.write { writeDB in ...

编辑:我在这里留下这个问题,但是我想我可能会过早地进行优化。我将尝试使用dbQueue而不是dbPool来查看性能。如果速度需要,我将回到dbPool。

1 个答案:

答案 0 :(得分:1)

GRDB数据库访问方法不是可重入的(DatabaseQueue和DatabasePool的读取和写入方法)。

为帮助您解决问题,请尝试将数据库访问方法分为两个级别。

第一个级别未暴露给应用程序的其余部分。它的方法都带有一个db: Database参数。

class MyStack {
    private var dbQueue: DatabaseQueue

    private func fetchFoo(_ db: Database, id: Int64) throws -> Foo? {
        return try Foo.fetchOne(db, key: id)
    }

    private func setBar(_ db: Database, foo: Foo) throws {
        try foo.updateChanges(db) {
            $0.bar = true
        }
    }
}

第二级方法公开给应用程序的其余部分。他们将第一层方法包装在readwrite数据库访问方法中:

class MyStack {
    func fetchFoo(id: Int64) throws -> Foo? {
        return try dbQueue.read { db in
            try fetchFoo(db, id: id)
        }
    }

    func setBar(id: Int64) throws {
        try dbQueue.write { db in
            guard let foo = try fetchFoo(db) else {
                throw fooNotFound
            }
            try setBar(foo: foo)
        }
    }
}

第一级方法可以根据需要进行低级设置,并且可以组成

第二种方法是高级方法,并且不可组合:由于“数据库连接不可重入”致命错误,它们无法相互调用。它们提供了线程安全数据库方法,可确保数据库的一致性。

有关更多信息,请参见Concurrency Guide

相关问题