世博会使用现有数据库

时间:2019-04-10 22:52:43

标签: sqlite react-native expo

根据expo sqlite文档的react-native,我可以像这样初始化数据库:

const db = SQLite.openDatabase('db.db');

这有效,我可以像这样更新数据库:

  update() {
    db.transaction(tx => {
      tx.executeSql(
        `select * from items where done = ?;`,
        [this.props.done ? 1 : 0],
        (_, { rows: { _array } }) => this.setState({ items: _array })
      );
    });
  }

据我有限的理解,这会在设备中创建一个数据库。然后对它进行操作,使所有数据库保持本地状态。

我有一个已经建立了所有必要表的数据库。如何使用已经设置好的当前数据库?

例如:(语法不正确)

const db = SQLite.openDatabaseIShipWithApp('mypath/mydb.db');

我找不到任何文档可以帮助我。 我上面提到的唯一原因是因为我已经拥有带有表和数据的数据库。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:1)

如果在资产中使用本地预填充数据库:

import * as FileSystem from "expo-file-system";
import {Asset} from "expo-asset";

async function openDatabaseIShipWithApp() {
    const internalDbName = "dbInStorage.sqlite"; // Call whatever you want
    const sqlDir = FileSystem.documentDirectory + "SQLite/";
    if (!(await FileSystem.getInfoAsync(sqlDir + internalDbName)).exists) {
        await FileSystem.makeDirectoryAsync(sqlDir, {intermediates: true});
        const asset = Asset.fromModule(require("../assets/database/mydb.sqlite"));
        await FileSystem.downloadAsync(asset.uri, sqlDir + internalDbName);
    }
    this.database = SQLite.openDatabase(internalDbName);
}

这将创建SQLite目录和数据库(如果不存在)。否则,FileSystem.downloadAsync()会在新安装的应用程序上引发错误。

一些评论:

  • 您不能在require()(仅字符串)中使用变量。参见例如this

  • 您必须明确允许扩展名.db.sqlite在Expo中加载,请参见this。您必须在根目录中创建文件metro.config.js

const defaultAssetExts = require("metro-config/src/defaults/defaults").assetExts;

module.exports = {
    resolver: {
        assetExts: [
            ...defaultAssetExts,
            "db", "sqlite"
        ]
    }
};
  • 并且可以在app.json
  • 中添加以下内容
"expo": {
  "assetBundlePatterns": [
    "**/*"
  ]
}
  • 如果要删除已加载的数据库(例如用于测试),则必须在“电话”设置中清除整个Expo App数据(删除缓存不足)。或编写这样的方法:
async function removeDatabase() {
    const sqlDir = FileSystem.documentDirectory + "SQLite/";
    await FileSystem.deleteAsync(sqlDir + "dbInStorage.sqlite", {idempotent: true});
}

答案 1 :(得分:0)

我认为在世博会上这是不可能的。如果您使用的是裸露的android项目,则有一种使用现有数据库的方法,其中涉及编写一些本机代码以将数据库从项目资产复制到应用程序的电话的标准位置(/ data /等)。

https://medium.com/@johann.pardanaud/ship-an-android-app-with-a-pre-populated-database-cd2b3aa3311f

我总是亲自使用CREATE TABLE if NOT EXISTS亲自创建数据库,因为sqlite要求您在查询之前定义架构。如果需要播种数据库,则此步骤之后将执行其他步骤以插入所需的数据。

在大多数情况下,您还需要检查参考数据并定期从服务器进行更新(从发布apk到下载该应用的人,它甚至可能会更改),并且当没有此代码时,此代码也将起作用数据库中的参考数据。

有一些服务试图消除他的麻烦(例如解析),但是您将需要确定对它们托管数据是否满意。)我没有使用过它们,所以不确定完全可以正常工作,但有人告诉我它试图解决离线第一类问题。

请记住,在将来的迭代中,您可能需要修改未来版本的结构(以添加字段等),因此您可能需要定义一些在首次启动应用程序时加载,检查数据库版本并应用所有更改的代码使数据库达到适当级别所需的资源。

答案 2 :(得分:0)

我能够通过使用expo的FileSystem.downloadAsync实现此目标:

首先,我导入了它,因为我正在使用博览会管理的应用程序:

import { FileSystem } from 'expo';

然后我从服务器这样下载它:

// load DB for expo
FileSystem.downloadAsync(
  'http://example.com/downloads/data.sqlite',
  FileSystem.documentDirectory + 'data.sqlite'
)
.then(({ uri }) => {
  console.log('Finished downloading to ', uri)
})
.catch(error => {
  console.error(error);
})

第一个参数是位置的uri,第二个参数是我要放置的位置。在这里,我正在使用documentDirectory。