2017-01-23 42 views
0

我的應用程序我有一些模型,需要添加一個新的列。Appcelerator合金移植拋出SQL錯誤,當新應用程序被安裝

因此,根據documentation,我編寫了一個帶有SQL「alter table add column ..」的遷移文件,並將該屬性添加到合金模型文件中。像預期的一樣,這工作完美。

但是,當應用程序首次安裝在設備上時,會引發SQL錯誤,說我的遷移嘗試添加的列已經存在。由於數據庫模式是從模型文件創建的,我猜這個例外是正確的,但我想知道如何完成現有和新安裝的APPS的數據庫更改。刪除遷移文件,只需將該屬性添加到模型文件,將使其適用於全新安裝,但不適用於更新。

最好的問候, 斯文

更新1: 我嘗試添加一個初始遷移,而新的字段創建表,然後加在另一個移民新領域(見雷的答案)。還是一樣的錯誤。

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(與解決方法解決方案): 因爲我知道我運行使用該信息爲條件加入列(如塞薩爾提議)遷移時,該表應具有的列數。

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"); 
} 

};

+0

根據Cesar的答案添加了解決方案解決方案。不要那麼喜歡那個,但是現在確實如此。 – Sven

+0

順便說一句,遷移1是不需要在我的情況! – Sven

+0

我不知道SQLRest遷移是否正常工作?自定義適配器的問題在於它可能與其他方式的工作方式不同...... – Ray

回答

0

數據庫遷移在應用程序開發中始終是一件複雜的事情。也就是說,有些優點和缺點會在某些時候讓你消滅整個數據庫,並從頭開始重大更新。

好事是,你應該能夠在migration.up功能做一個簡單的SELECT和驗證檢查,如果列中存在與否,無論它是否是使用成功的查詢http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Database.ResultSet-method-isValidRow

你可以也可以通過在數據庫架構的每一項變更中添加一個Alloy.Globals屬性來「版本化」數據庫。類似Alloy.Globals.DatabaseVersion = 1,並在migration.upmigration.down函數中對此進行驗證,這樣您至少可以知道自己在當前數據庫模式中的位置,以及您希望位於遷移數據庫模式中的位置。

不太好事情是,每改變一次,你將不得不編寫代碼來管理所有可能的用例(例如,版本1的用戶跳到版本3而不用2),所以想想這也如你所願。

+0

感謝您的評論。實際上,在其他項目(Java,flyway)中,遷移對我來說非常合適。這裏的問題是我看不到數據庫安裝和遷移的順序的任何規則。我自己對數據庫進行版本控制對我來說不是一種選擇,因爲這是我期望的唯一一種遷移框架;)我將使用isValidRow函數檢查解決方法,並在此處報告結果。 – Sven

+0

根據您的建議更新瞭解決方法的初始問題。謝謝。 – Sven

+0

我很高興它幫助你。就我個人而言,我嘗試遠離允許模型,因爲我在我的項目上調用的API比適配器可以做的更復雜。我還使用[joli](https://github.com/xavierlacot/joli.js/)來管理本地數據庫,並且它工作得很好。 –

0

斯文,首先檢查了這一點:https://medium.com/all-titanium/using-models-and-migrations-in-titanium-a03e3a6b0d6f#.2qb9oj3rh

我想你遇到的問題是,你需要有一個具有使用CREATETABLE您的原始模型建立的初始遷移。然後應用遷移。那應該工作。

Ray

+0

雷,感謝您的鏈接。我之前閱讀過有關最初的遷移文件,但它不適合我。奇怪的是:createTable遷移正在運行,沒有任何異常,所以我期望表中不存在。下一次遷移(添加新列)會因列重複違例而失敗。實際上我看不到任何規則,從模型創建遷移/模式的順序被執行。我將用更多關於appcelerator版本和連接器的信息來更新最初的問題。 – Sven

+0

也許發佈你的模型和遷移也會有所幫助 – Ray

+0

剛剛添加了一些代碼 – Sven