I have an application that syncs with a web server. When I update I want the row ID's to match with the ones in the web server, because other data depends on correct mapping of row ID's. I have thought of just clearing the table each time, but I don't think that is a efficient way especially when the data gets very large. What is an efficient method for this?
I'll make it easy for you:
1) Add an extra column to your android db table, lets call it web server id.
2) When you first create the android table, insert the web server row id into this column.
3) Whenever you synch with the server, use that id to find the proper web server row to synch with.
This is all Database 101 stuff. You should really read up on foreign keys. It is clear the relationship is preserved even when data is changed, unless you are changing the key fields. However, the key fields should never be altered so the relationship will always be preserved.
Related
I have a remote database that can change at any time. I need to find a way to keep my sqlite database update with all the changes in the better and optimised way possible.
I thought having a single timestamp per table and send only the updated table to the client would be one solution, or maybe having one timestamp per row and sending only the updated row to the client..
But
- how can i manage deleted items, for example?
- how can i manage the technical update on Android?
Basically, in a few words, at some point in the app, i need to download the changes with an API and update the local db.
Does anyone have some ideas?
Thanks
Since it seems this is a one-way only sync, I would:
Make each table on the server DB have a UUID column and a last
updated date/time column.
Create a REST call that will request updated data. Ideally, it would
take the time the client was updated. This date should come from the
server during the update call.
The server would scan each table searching for rows that have a date > than the date passed. Serialize the data and return it as JSON along with the server date/time for the next request.
Now tracking deletes is a bit more work. You can either:
Never delete data and only mark the rows as deleted, this is the easiest, but depending on your data may end up with lots of rows in the DB.
Delete the data and then track the deleted rows in another table. These can be deleted after some time and if/when all clients have been updated.
Have a second update call that will push down all the UUID values and time stamps for each row. The client could then figure out which rows need to be deleted.
Though it's the most complex, I'd probably opt for option 3, as I don't like old data hanging around. The direction I would go would also depend on how many clients will be syncing with the DB.
I've decided to follow another approach:
I've created an api that parse the Mysql db into an SQLITE db on the SERVER side. There is a "last_update_timestap" that will be updated every time that something will be changed.
Another api call, gives in the header an extra field containing that timestamp.
On the client side there is a Sync process that do the follow when needed:
Api call retrieving just the HEADER, getting the last update timestamp and checking if an update is needed;
If is needed download the database from the other api
Write the database into a temporary file and copy that temporary file at the position and with the same name of the real database
Use the database
Thanks everyone for the help but this turned out to be the suitable approach for my project structure.
I've an Android application that connects to a server api (CRUD) to manage a model. The app needs to work offline, therefore the app has a database that stores the data pulled from the server.
The instances of the model have an attribute named ID which is created in the server.
In order to perform a create offline operation I a difficult problem. As there is no connection I need to store the entity to the database, however it does not have an id yet.
Which is the best - general solution to do this?
Should I add a second attribute in the database that will be the "temporal id" (for example using an UID)?
Maybe I don't add this data to the database but to a temporal queue?
What happens with the relationships with this entity?
You always will need a local id for your rows, used as primary key (the could be incremental, that will make things easier). After that anytime you sync with your server you will have a remote id aswell, this remote id will be used to link your local row with a remote row in your server.
So,
-when you get a row from the server, make sure you fill your remote id and let SQLite to fill the local id,
-when you create a row from the mobile (or all the entries in your database without remote key), send it using your local id (which will be ignored from the server) and then assign a new remote id from the server. Finally your server should return the new rows with the remote id field filled, making the whole cycle.
Hope it helps
EDIT:
In order to make this work, your mobile and your server tables will be slightly different. In your server you will have a local id, this local id will have to match your remote id in your mobile.
If you get fom the server a row you will need to check if you have the remote id (that is your linker field). If you do not have any rows with that remote id, you will be inserting new rows, otherwise you will be updating them.
There is only one more thing to complete this process, when you send a row to the server you will need an extra field (in your json or your xml) which will tell you that your row is yours.
Exists only one case in which you will receive a mobile local id from the server, and it is when you upload new rows.
In this case you will receive your mobile local id, and the remote id. Now you will be able to link the local information with the remote one.
Summarising:
When you get new rows from the server, you will receive only mobile remote id (server local id), use this remote id, to check if you have to update or insert.
When you send rows to the server, the server will return you the local mobile id and the remote mobile id, this way, you will know that the received rows are yours. In this case, you will have to update your local rows to store the remote mobile id.
The server will never store local mobile ids as it makes no sense.
Iam following this tutorial :- http://azure.microsoft.com/en-us/documentation/articles/partner-xamarin-mobile-services-android-get-started/
to use mobile services with Azure.
Currently when I add items to the table, the data gets stored randomly. I want it to store the items in a such a manner that the latest record comes at the top of the list.
How can I do it?
Thanks
From the looks of that tutorial, the table in the database which has been created is using a UniqueIdentifier (equivalent to a GUID in code) as the Id. (presumably PK).
GUIDs are generated "randomly" and don't sort nicely in chronologically created order. It's not that the data is getting stored randomly. The Guid is randomly generated, and the table/index stores it in exactly the correct place based on it's Id value.
At the end of the day, for such a small amount of information, the order it's stored in the table isn't really important so long as you can retrieve it in the order you want.
From the looks of the demo, the data table also has a _createdAt column on each data entity. Have a look in the TodoItem & TodoAdapter code to find where it actually executes the query against the data store. It should be quite easy to add an OrderBy to that call to force the returned order to sort by _createdAt
I have a bit of a theoretical question for which there is no code yet as I am still just in the thinking stage. I want to update an app to allow users to share their data with others through DropBox Datastore or something like that. However, when a user creates data which get populated into multiple sqlite tables on the device, each table has an auto-incremental integer as a primary key that is used as a foreign key in other tables to link the data.
If there is more than one user actually creating the data and sharing it then the primary key columns are obviously going to be an issue. If I download the data and store it locally I obviously can't insert user 1's key value in user 2's data table, firstly because of the auto-increment and secondly because user 2 might already have data that is not shared saved with that key value.
I have thought about a few options but nothing is particularly appealing or robust. I was thinking about creating a UUID to identify the device, that value would have to be stored in each of the tables and the primary key would be a combination of that column and the current primary key integer which would obviously have to have the auto-increment removed. So to pick up all related data from each table the id column and UUID column would both have to be used.
I feel like there must be a more robust method of achieving this though, any one have any better suggestions?
If I'm understanding well you need some sort centralised database in the cloud to communicate with your local app, is that right?
A client should never create the ids for such a system. A usual practice on these cases is to always have a remote id which is created by your DB in the cloud, and whenever you don't have this value yet, you can have a fallback value (local id created locally - which is different from the remote one).
So, to illustrate my words we could set the following example. Your app stores messages in database. Say you create messages with a local id 1,2,3. Those ids will never be meant to be unique in your central database in the cloud. Instead, you'd just use them as a local fallback. As soon as you can send those 3 messages to your centralised database, it'll give them 3 new remote ids you'll use for unique means (ie.: 35, 46, 54).
Note that when you have multiple requesters/users accessing one same database there's not such way to assure uniqueness unless you follow the explained approach, or you query a certain number of unique ids in advance and on demand to your database in the cloud.
Keep in mind, that the actual truth can be only delivered by the databases in your servers.
I am currently using PHPmyadmin to store data in my mySQL database. The android application I am developing requires the user to select some data and this data along with its attributes need to be stored in my mySQL database. I know I have to create a unique table for every user who downloads my application but how do I go about doing this without having access to the program which the user downloads ?
For eg: let us say there are two phones which download my application. I would want to create two tables in my database which the particular phone knows and can access
Creating one table for every user is a terrible approach. Instead you should create a users table, with a unique ID set to auto_increment, to generate those unique IDs. Then use separate tables to store the data you might need, referencing the user ID from the users table.
It might sound a little confusing, but there are lots of good reads about this on the Internet.
You can generate unique user id in php using uniqid(”, true) function.