This is my first time working on a Xamarin App and I am new to the app development world so I need some help figuring out this process.
Currently I run a php web service that generates some SQL files that I run in DB Browser and I get a database file which I then put into my Assets and Resources Folder. Using each platform's API I copy the database into a writable folder and use that to run my queries.
I followed this really helpful tutorial and it worked perfectly fine.
https://medium.com/#hameedkunkanoor/creating-a-sqlite-databse-and-storing-your-data-in-your-android-and-ios-application-in-xamarin-2ebaa79cdff0 .
After the "initial" setup I store a timestamp in a local table and and the next time the user opens the app I pass that timestamp and retrieve data that is older than that timestamp. The I update that timestamp and continue the process. That data is sent back in JSON format and make the updates to the tables.
My only concern is if a new version were to come out where I add a new table or a new column which is not present in the current version of my Database, how should I take care of those update Web Service calls? Is there a way of monitoring my DB version? I read somewhere where I could just ignore the new data that is not present already, like table or columns, but I'm not really sure how to do that.
I also saw that if I call CreateTable on my current tables I could potentially update them?
Also for future reference each time I develop a new app would I need to regenerate a new database file to store in the assets/resources folder? Is there a more automated process for this? Along with monitoring the version of my database?
Any Help/Tutorials/Suggestions would be greatly appreciated.
You have to remember that CreateTable it's already doing the columns update for you, because internally it calls a method called MigrateTable which you can see here for further clarification: https://github.com/praeclarum/sqlite-net/blob/master/src/SQLite.cs#L562.
However you could have to handle more advanced modification to your database, like adding triggers or something similar.
In that case i suggest you to perform modifications manually.
In Xamarin Forms i've ended up with this:
https://gist.github.com/matpag/b2545cc22c8e22449cd7eaf6b4910396
Could not be the best strategy ever but seems to work for me.
Summarizing :
You have to save the database version in an internal flag of the SQlite database called user_version accessible with PRAGMA keyword.
Every time you get the database connection, you have to perform a check and see if the current database version is the same as the app last database version.
If not you need to perform a database update and set the new current version.
Reference here.
Related
I'd like to receive some advice from all of you.
What is the best way for me to alert users on an update to my app? My app is a very knowledge-based & it works like a dictionary, so there will always be updates to it.
The database I have used is by DB Browser for SQLite, and they are all local database where it is uploaded into the assets folder in Android Studio.
Currently, the limitations are that:
1) it's obviously not real-time because it's stored locally;
2) every update I make to the database structure, I am required to upload the new database into the assets folder again, followed by uninstalling the old app on my phone, then run the app to install in my phone again so that the new database is overwritten.
I have read (How can I regularly update a database of content on an Android app?) & some others, and it seemed like I have to have a server, a cloud-based database & live app in market, to solve the limitations?
Is there really no way for me to overcome the limitations if I want to stick to a local database? At the same time, I kinda wish to avoid setting up a server because I am not intending to make the app live on market, and also this is just a school project I am working on and as such, I have very limited skill sets & knowledge about it and would like to make it on a school-project-based level.
Thanks in advance.
One way to do it is to connect to your local DB through local network instead of assets folder. Therefore, you can update the information by querying the local DB.
As for syncing the information between DB and your application, you should create a trigger or watcher that notify your application when the DB is updated. Therefore, your application can know when to query the DB for the updates. Another way is to just query the database periodically.
Bonus: you could move your database to a cloud-based database. Usually there are several providers that provide free database hosting up to a certain size, which should be enough for your project.
i have the problem that when i release new version of my application, if i add a new column to one of my db tables, the database doesn't update. Any one know how to create a script of upgrade versione in case there are new columns or new tables??
Thanks
You have to remember that CreateTable it's already doing the columns update for you, because internally it calls a method called MigrateTable.
However you could have to handle more advanced modification to your database, like adding triggers or something similar.
In that case i suggest you to perform modifications manually.
In Xamarin Forms i've ended up with this:
https://gist.github.com/matpag/b2545cc22c8e22449cd7eaf6b4910396
Could not be the best strategy ever but seems to work for me.
Summarizing :
You have to save the database version in an internal flag of the SQlite database called user_version accessible with PRAGMA keyword.
Every time you get the database connection, you have to perform a check and see if the current database version is the same as the app last database version.
If not you need to perform a database update and set the new current version.
It's not a matter of a script, as there isn't such a thing. You can release a version with a "patch" that will run once, extracting all your records to a temporary form -> deleting the table -> creating it again (will assure it's created with the new columns and so on) -> reinserting the records again. After a while, when you know that all your users (or whenever you set the limit) have moved to the newer version you can just eliminate the "patch" from your code.
Hope it helps.
The automatic migration feature is still not working in sqlite.net-pcl, but it looks like it does work in the other sqlite package: sqlite-net-pcl, which is actually the Xamarin recommend sqlite package.
I have an online (postgresql) database, and a local copy of the db in an Android app. The data in these is synchronized, so the app can function offline, but can download new data and upload results when it can. Data is transfered via http GET and POST requests.
I have no problem synchronizing the data for known tables, however, I would like it to be possible to create new tables/alter tables in the online database and have that change reflected in the Android db automatically i.e. without having to release a new version with the updated synchronization code. Is there an obvious/standard way to do this that I haven't found? Google searches I have performed just refer to database migrations for two of the same system or for known schema.
Is there an obvious/standard way to do this that I haven't found?
There's no "standard" way but there are ways to do it depending on your requirements and how your app works.
It's actually a broad question but solvable if you give it a bit of thought.
My app downloads data from a server on a daily basis. Part of the download process involves downloading a DB version file (just a plain text file) similar to the following...
db_version=12345
...the string representation of the previous version (if any) is saved in SharedPreferences as an int value.
If the version in the file is greater than the one in SharedPreferences, the downloader pulls some text files which contain SQL commands for creating, dropping, altering tables etc. Only after the changes have been successfully made does the downloader pull the actual data files and update the DB data (not forgetting to update the latest version in SharedPreferences).
If the version in the file is the same as in SharedPreferences then obviously the download simply does the normal daily data download and DB data update.
I have an app that creates a database and do some stuff. I am wondering if i upload a new db to a server and download it to the exact folder where the older one exists it will be overwritten and i am good to go? Or there will be a problem. Assuming it has the same name, same column names, etc. Of course i am reffering to sqlite.
In Android, when performing a database update you should be using onUpgrade inside of the SQLiteOpenHelper. One way of doing this is to download text files that include the sql instructions needed to modify the current database or update rows with new data. The reason you have to do this is because Android will only create the database once. After the initial creation the call to onCreate for the database will not occur.
What is the best way to work with the sqlite database in android?
The sqlite database file (copy it for the first time into the application environment)
OR
Creating the tables in code (in database helper's onCreate())
My database has 6 tables and it is empty for the first time. I ask this because I want to update my database in the future and would want to know the best approach for this.
Thank you!
You should create (in code) it the first time it is used. Android offers the SQLiteOpenHelper class that should be used for it. SQLiteOpenHelper defines the following methods:
onCreate(SQLiteDatabase db): invoked when the database is created, this is where you can create tables and columns to them, create views or triggers.
onUpgrade(SQLiteDatabse db, int oldVersion, int newVersion): Invoked if the used database is older than the current version. Handle here the upgrade stuff (data migration, table creation/deletion)
See here for a good tutorial: http://www.codeproject.com/KB/android/AndroidSQLite.aspx
If you don't expect to have your db updated by user interaction, the file might be the best option, especially in the case that you have a lot of data to insert (file copying vs a bunch of inserts).
On the other hand, if you expect to have some data altered or added by the user, the file approach will work only in the first release.
Any time you will need to update your schema or add new data (releasing an upgrade), you will need to consider that the existing data might be changed or enriched by some stuff that the users will expect to find AFTER the upgrade.
So replacing the file is not an option anymore.
In case you need to use the sqllite helper approach, I'd love to hear some feedbacks on my sqllite helper code generator that you can find here: github
Not specific to SQLLite or android, however I have worked on a Windows trading application where users could save down Xml 'documents' - ie: a custom view saving their reporting preferences and various other flags which could then be shared around the team. On startup a user's profile was loaded and their documents parsed to customize the UI.
The application was to have a release every 3 weeks and existing documents needed to work with the new application. This was a problem as occasionally the XML schema changed resulting in new or deleted fields.
The solution we came up with was to create an abstract type called Patcher. Each release could have one or more DerivedPatcher types with it which were run on the first load after an update. The Patcher would have an abstract method to patch the XMl documents. Meaning an XML document would be loaded in with the old schema and upgraded, saved back in-place using the new schema. The Patcher would also have a rollback method to allow unrolling if an error occurred.
The same approach could be applied to tables in a database. Basically if you can create a patcher or PatchManager to serialize key tables to XML in memory, then apply the DB changes and write the data back, you can achieve database migration in a generic, re-usable way.
A key benefit of this method is it can be tested on developer PCs before deployment, so long as you have access to some sample SQLLite data. Knowing how your users use your application is key here.
For large amounts of data you might want to consider this kind of solution: Create an empty database in code and provide an activity which responds to an intent with this action: android.intent.action.SEND. Respond by parsing the sent file and populate the database with the contents. Design a format which can be easily parsed (XML is not needed for everything ;-) so the code to parse the file and fill the database is small (my binary for this including an UI to show progress (which is the larger part of the activity) is less than 12 kB in size).
The file may be distributed separately (extra apk, download, whatever). The benefit of this approach is that you do not need to store your initial database content within the apk and thus the data is only stored once on the device (after the file has been deleted). Otherwise you have the data in the database plus the source code or asset in the apk.