samedi 2 mai 2015

Possibly huge transaction with ContentProvider

I have an application which uses SQLite directly, but now I would like to migrate to using a ContentProvider, also locally, as I want to use CursorLoader and search suggestions. But I have a question about transactions.

In my app, a part of the workflow is to 'import' a possibly huge data set into the database, atomically. The data that I want to import comes from a custom text format which I stream-parse (kind of like SAX: I don't parse the whole file and keep it in memory; rather, I can parse line by line) and when an entity is discovered an insert is issues. The entities form a 3-level hierarchical structure. Up until now, I have been using plain SQlite and transactions: when import/parsing began, I started the tx, and after it was finished, I would rollback or commit it. This way I was sure it was atomic, i.e. any error in the input file would not result in garbage in the database.

With content providers, the problem is not so simple. I can't start my own transaction easily; I can't use bulkInsert because I need to use back references for child entities, which means I need to use the applyBatch method (and override it to start and end the transaction, as I require it). The problem is that it requires an ArrayList of operations, and I just don't know how many there would be, and don't want to keep them all in memory at once.

Maybe I can use the ContentProvider for normal db access, but the plain SQLiteOpenHelper for data import? But then, it is possible that two helpers are open and use the database (the reads and imports are async) at the same time, which would result in an exception saying two processes use the same database (don't remember the exact exception type). I also can't pass my own helper to the content provider.

So, what I could do it to use the ContentProviderClient.getLocalContentProvider as I know it is mine, and use its implementation details - either fetch the sqliteopen helper it uses, or use the methods to start and finish transactions. This seems to be the best solution to me, if it works.

How is this normally done?

Aucun commentaire:

Enregistrer un commentaire