Appcelerator Alloy迁移在新安装应用程序时抛出SQL错误

时间:2017-01-23 17:14:26

标签: appcelerator appcelerator-alloy

在我的应用程序中我有一个带有一些列的模型,需要添加一个新列。

所以根据documentation我用一个SQL“alter table add column ..”编写了一个迁移文件,并将该属性添加到合金模型文件中。与预期一样,这完美无缺。

但是,当应用程序第一次安装在设备上时,会抛出SQL错误,说我的迁移尝试添加的列已经存在。由于数据库模式是从模型文件创建的,我想异常是正确的,但我想知道如何完成现有和新安装的APPS的数据库更改。删除迁移文件,只需将属性添加到模型文件将使其在全新安装时工作,但不在更新时工作。

祝你好运, 斯文

更新1: 我尝试添加初始迁移,创建没有新字段的表,然后在另一个迁移中添加新字段(请参阅Ray的回答)。仍然是同样的错误。

Appcelerator版本:5.2.2

模型适配器类型:sqlrest

更新2(部分代码):

模型:

config: {
URL: Alloy.Globals.jsonEndPoint + Alloy.Globals.jsonRequestParams + "foto",
columns:{
    id:                                     "INTEGER PRIMARY KEY AUTOINCREMENT",
    dateiname:                              "TEXT",
    beschreibung:                           "TEXT",
    primaerfoto:                            "TEXT",
    aufnahmedatum:                          "TEXT",
    anlage_id:                              "INTEGER",
    foto_label_id:                          "INTEGER",
    latest_sync_date:                       "TEXT",
    dirty:                                  "INTEGER",
    begehungsbericht_protokoll_id:          "INTEGER",          
    begehungsbericht_protokoll_server_id:   "INTEGER",          
},
adapter: {
    remoteBackup: false,                        //Prevent database from being saved in icloud   
    db_name: this.Alloy.Globals.currentDatabase,
    type: "sqlrest",
    collection_name: "foto",
    idAttribute: "id"
}

迁移1:

migration.up = function(migrator) {
Ti.API.info(">>>>>>>>>>>>>>>> migrate create table UP <<<<<<<<<<<<<");
migrator.createTable({
    columns: {
        id:                                     "INTEGER PRIMARY KEY AUTOINCREMENT",
        dateiname:                              "TEXT",
        beschreibung:                           "TEXT",
        primaerfoto:                            "TEXT",
        aufnahmedatum:                          "TEXT",
        anlage_id:                              "INTEGER",
        foto_label_id:                          "INTEGER",
        latest_sync_date:                       "TEXT",
        dirty:                                  "INTEGER",
        begehungsbericht_protokoll_id:          "INTEGER",
    }
});

迁移2:

migration.up = function(migrator) {
Ti.API.info(">>>>>>>>>>>>>>>> migrate ALTER table UP <<<<<<<<<<<<<");
migrator.db.execute('ALTER TABLE foto ADD COLUMN begehungsbericht_protokoll_server_id INTEGER;');

};

更新3(解决方法与解决方法): 由于我知道运行迁移时表应该具有的列数,因此我使用此信息进行条件添加(如Cesar建议)。

migration.up = function(migrator) {
Ti.API.info("migrating foto table");

var rows = migrator.db.execute("SELECT * FROM foto");
Ti.API.info("field count: " + rows.fieldCount);

if (rows.fieldCount < 11) {
    Ti.API.info("adding column: begehungsbericht_protokoll_server_id");
    migrator.db.execute('ALTER TABLE foto ADD COLUMN begehungsbericht_protokoll_server_id INTEGER');
} else {
    Ti.API.info("NOT adding column: begehungsbericht_protokoll_server_id");
} 

};

2 个答案:

答案 0 :(得分:0)

数据库迁移在应用程序开发中始终是一个复杂的部分。也就是说,有一些优点和缺点会使你彻底消灭整个数据库并从头开始重大更新。

好事是您应该能够检查列是否存在,方法是在SELECT函数中执行简单的migration.up并验证是否存在是使用http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Database.ResultSet-method-isValidRow

的成功查询

您还可以通过在对数据库架构所做的每项更改中添加单个Alloy.Globals属性来“版本化”数据库。类似Alloy.Globals.DatabaseVersion = 1之类的内容并在migration.upmigration.down函数中对此进行验证,这样您至少知道自己在当前数据库架构中的位置以及迁移数据库架构中的位置

不那么好的事情是,每次更改都需要编写代码来管理所有可能的用例(例如,版本1的用户跳转到版本3而不会转到2 )所以当你走的时候想想这个。

答案 1 :(得分:0)

Sven,首先要检查一下:https://medium.com/all-titanium/using-models-and-migrations-in-titanium-a03e3a6b0d6f#.2qb9oj3rh

我认为您遇到的问题是您需要使用createTable进行原始模型设置的初始迁移。然后应用迁移。 应该工作。