I have an SQLite database for my Android app that stores a copy of some data from another database on a server. When the user opens the app, I want to sync the local copy to the external master. The user may have been on the related website and inserted/updated/deleted data.
If it was just insert/update, timestamps could be used, but as they could delete data, I'm not sure how to go about checking for deleted rows.
So, what's the best way to tell what's changed and update the local copy?
I'd add a table to audit the deletes (containing key fields of the deleted records) and transfer that on sync, and after a successful sync clear the table down.
Hm, we are working on iOS project, which will sync it's database with server if server will respond what it have newer version.
Our server incrementally stores performed SQL and on request if compounds all those changes to specific date and gziped sends to the application, where my Objective-C wrapper execute SQL statement from downloaded file.
May be same approach will be good for you too.
Related
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.
I have started working with databases lately, I was able to create a local database and manage it in my Android app. Now I want to move to higher level with it but I don't know how to do it.
The users in my app need to be able to modify the database, for example insert new data in it. When a user insert new data in the database I want other users to see this change in their copy of the database.
I understand that I will need to store that database on a server or something and synchronize it with the users.
Can anyone tell me the steps to do so?
You should perfom this task in steps.
First, make the local database, and use a system to know when/what changed.
I usually work with triggers myself, but any "mark" is enough to synchronize.
Then, you must make a replica of that database somewhere else. Realise that maintaining the databases is a process, any change in the structure of one database must be performed in all other as well.
Finally, you must implement a method to transfer the data.
So, for an example:
db_local the database in the device.
db_outside the database in the internet.
db_local.trigger -> onInsert
On the applications, check for internet, then connect to your server, then upload the same command to db_outside and run it...
In this step, you must handle connection issues, and if the SQL command was succesfully executed, you have replicated the database content.
Once you have the replicated database, inform a system (like google cloud messaging), that the database was changed, and have the other users pull the info.
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 a local sqlite database in android app running on multiple devices to sync with remote database. Everytime I fetch data to show on UI, I got data from local database, and later query from remote database and insert them into local database, using below code:
database.replaceOrThrow(TABLE_NAME,null,values);
this runs ok except for someone delete from one device. How do I got to know which row in my local database need to be removed when the row in remote database is deleted?
there are two options which I don't like either:
1) clear the local data whenever I fetch from remote
2) compare local data with remote data to find out which row is missing in remote data, and then delete from local database.
Is there any best practice for such common situation? Thanks!
I'd go with option number 2. You can easily calculate the delta between your local DB and the remote. For instance, you can create two ArrayList's containing the projection over the primary key or another key of your records. Then you calculate the difference between the local list and the remote list with removeAll(Collection). At this point you have a List of all the keys of records which no longer exist in your remote DB and which therefore can be erased from your local DB.
May be you can try this out:
Store the time
at which the Modification is Done is your Remote Db.
In Shared Preference Store the Time of your table creation and updation.Also update accordingly.
Finally compare : remote_table_time > table_time and fetch those entry whose time is greater than your table creation time
Applying any hand rolled syncing logic will be complex, difficult to debug and a nightmare to maintain. Your issue seems to assume that the remote DB is the source of truth but if you are allowing users to make data changes while "offline" then you need to retrospectively sync local changes to the remote store also.
I suggest you take a squiz at the sync adapter.
I am implementing an android application and i can't figure out how to solve this problem
I'm trying to deploy an application with an existing SQLite database.
when user install application at the first time , Database will download but as trial version , with few records only , there are 10 feature extra than trial version when user select to buy one of them database should updated with new records from server , new records have the same schema of trial version database , so i want to insert purchased records to old database without delete old version and install new one with purchased feature
It seems that the most direct method would be to have separate text files containing the SQL commands to insert the data for each different upgrade.
Then your app can download said file, read the text file and execute the SQL commands contained therein, adding the data necessary.
You could either have the raw SQL in the file and use the rawQuery() method (somewhat dangerous IMO) or you can create a data structure to be read in by your app that takes the data and drops it into a method that can be parameterized like .insert().