SQLite data cleanup in Windows 8 application - sqlite

In my windows 8.1 application i am using SQLitePCL on top of SQLite.
I create the tables and populate my test data on application launch.
I only create DB tables if the tables are not existing through SQL is exists keyword in the queries.
Now how do i clean up the populated test data. Do i have to run delete queries when application shuts down ?.
I am testing through Windows simulator 8. Is there no way to clean up the app data which will flush the db in the simulator ?
cheers,
Saurav

I suggest you to recreate DB schema every time you need to flush populated data. You have at least two options to achieve that:
At first: in the same way as you create DB tables if they are not exist, you can delete DB when the data should be flushed and recreate it. I use this code to open/create DB file.
private async Task<bool> IsDBExistAsync()
{
bool isExist = true;
try
{
StorageFile sf = await ApplicationData.Current.LocalFolder.GetFileAsync(DATABASE_NAME);
}
catch (Exception)
{
isExist = false;
}
return isExist;
}
At second: open explorer window and navigate to C:\Users\{username}\AppData\Local\Packages\{package_family_name}\LocalState and delete DB file manually when it is not needed anymore. "package_family_name" is specified in Package.appxmanifest of your app (Packaging tab).
Bonus item: if you are developing phone part - you can access local storage using Windows Phone Power Tools utility.

Related

How to solve room data integrity error due to identityHash mismatch?

Issue:
Whenever I make changes to the database or the model, I get the following Room data integrity error:
My understanding is that I shouldn't need to increase the version number since I am using .fallbackToDestructiveMigration().
Background:
I using DB Browser for SQLite (v3.12.0) to make changes to the database.
I frequently make changes to my app/database, which is still in development. So, I am using a .fallbackToDestructiveMigration() (see codelab example).
File: RoomDB.java
#Database(entities =
{Note.class, Label.class, Join_ScheduleLabel.class, Schedule.class},
version = 1)
#TypeConverters(DataConverters.class)
public abstract class RoomDB extends androidx.room.RoomDatabase {
public static final String DATABASE_NAME = "vk_prepop.sqlite";
private static RoomDB INSTANCE;
public static RoomDB getInstance(final Context context) {
if (INSTANCE == null) {
synchronized (RoomDB.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.getApplicationContext(),
RoomDB.class,
DATABASE_NAME)
// Source: https://developer.android.com/training/data-storage/room/prepopulate
.createFromAsset(DATABASE_NAME)
// Todo: Remove Destructive Migration
// Wipes and rebuilds instead of migrating if no Migration object.
.fallbackToDestructiveMigration()
.build();
}
}
}
return INSTANCE;
}
public abstract RoomDao getRoomDao();
}
Troubleshooting Steps Taken:
Verifying the entities of the RoomDB.java file match the models and database.
Going into the App Info and tapping "Clear data" (see SO answer).
Uninstalling the app.
Making setting android:allowBackup="false" in the manifest (see SO answer).
Possible Solution:
In live-love's answer he says there may be an identityHash mismatch, but I am not sure how to resolve this using DB Browser for SQLite.
My understanding is that I shouldn't need to increase the version number since I am using .fallbackToDestructiveMigration().
The fallBackToDestructiveMigration only runs if a migration is required and there is no Migration covering the migration.
In your situation the issue is that you have included the room_master_table in the pre-packaged database and hence the identity_hash columns is available for comparison (which would be incorrect if changes were made to the schema that affected how room generates the identity_hash from the schema).
By including the room_master_table you are introducing an unnecessary complexity.
If you omit this table from the pre-packaged database, then it will be created and populated, with the appropriate identity_hash when it is created from the asset (i.e. when the database doesn't exist). As such you then only have to make the appropriate changes to the asset (the pre-packaged database), delete the current database (e.g. uninstall the App or clear the Apps data) and then run the App.
live-love's answer states that there may be an identityHash mismatch. Indeed this was the case. Here is how I resolved the issue using DB Browser for SQLite (v3.12.0).
Step 1: In Android Studio's project panel choose the "Project" view:
Step 2: Then double-click on the json file for your schema:
Step 3: Copy the identityHash in this json file:
Step 4: Open your database in DB Browser for SQLite. Click the "Browse Data" tab. Then from the drop-down menu choose "room_master_table".
Step 5: Compare the identifyHash from the json file in Android Studio to the identityHash in DB Browser for SQLite. If the hashes are different, this can be the cause of you Room data integrity error.
Step 6: So, paste the identityHash from the Android Studio's json file into the identityHash cell in the DB Browser for SQLite.
Step 7: Then press Ctrl+Shift+S to save the database.
Step 8: Click "Close Database".
Step 9: In your app on your phone or emulator go to "App Info" -> "Storage" -> "Clear data".
Step 10: Then in Android Studio press "Run app".
Problem solved... at least for me. If these steps did not help, please review these additional troubleshooting steps.

Moving from SQLte to Realm

I have a working app that uses SQLite as DB. I would like to move to Realm DB. Will this affect my existing users? How do I move over to Realm? My app is developed in Xamarin.
When you have created your schema, you need to iterate your sql values and add data in realm, for example(you need convert java to C#):
for (SqlTest sqlData : sqlTest) {
Test test1 = realm.createObject(Test.class, UUID.randomUUID());
test1.setName(sqlData.getName());
test1.setSex(sqlData.getSex());
}

Why is querying sql_master returnining nothing on some machines?

I recently changed some code I have using SQLite via better-sqlite3 to check if a table exists before running certain import queries.
The code and tests all run fine. But the tests don't pass on our build machines or on another developers machine. The tests are using an in-memory database, the problem hasn't occurred on any non-memory databases though it has only been ran on a half-dozen machines. There are tables in the database and code is able to read/write to them.
It turns out that the query I was using to check what tables I can import from was return an empty result. In fact, if I just query anything at all from sql_master in these cases I get an empty result.
// db is a database from better-sqlite3
private async getAllTables() {
var query = connection.db.prepare(`SELECT name, type FROM sqlite_master`).raw();
return query.all();
}
var allTables = await this.getAllTables();
console.log(`all things in sql_master: ${await allTables.join(", ")}.`);
The console has the following logged on the problematic matchines:
All things in sql_master: .
Locally it prints a list of all the things in sql_master as you'd expected. All the other queries my test code is doing is working as expected (reading and writing to tables besides sql_master).
The database was created like:
db = new Connection(":memory:", { memory: true, fileMustExist: true });

Qt - sync SQLite data base on application close

Data base is oppened in application by following code:
db = QSqlDatabase::addDatabase("QSQLITE");
bool dbExists = QFile::exists("base.db");
db.setDatabaseName("base.db"); // ":memory:"
if (!db.open()) {
db.close();
QMessageBox::critical(0, tr("Cannot open database"),
tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how "
"to build it."), QMessageBox::Cancel);
return;
}
if (!dbExists)
createDB();
I've mapped some tables to widgets via QDataWidgetMapper. All work fine during application run. Changes take effect. But all the chages are lost after restarting application with existing base.db. Application starts much faster, so it opens this file but with unchanged data base.
I've tried to close application by
db.close();
this->close();
There is no luck. Even the sync query did not help after db.open:
QSqlQuery query(db);
query.exec("PRAGMA synchronous = ON;");
What have I missed to sync changes to base.db?
UPDATE. You can try to build sqlwidgetmapper standard example and change :memory: to "base.db" file. It doesn't save changed data to file too.
Problem is possibly manual submit policy.
Either switch that to auto, or manually call QDataWidgetMapper::submit() at appropriate time (before new value is lost from the widget).

How to do concurrent read & write on SQLite database?

I am creating a Windows Store application, which takes a lot of data from web service daily and then insert/update data to SQLite. So the user has to wait till the data is downloaded to SQLite database then he is redirected to other screen whcih shows that downloaded data in user friendly manner.
Is it possible to run the downloading & database operations in background and user can use the app ? I tried to combine the downloading & insertion operations & UI of showing the data in single page but I am getting error "database is locked". If my app is suspended, will database insertion/update & web service call work in background ?
PS : I am using sqlite-net
You can do a number of inserts in a single transaction, like so
using (SQLiteConnection db = new SQLiteConnection("[database path]"))
{
db.RunInTransaction(() =>
{
db.Insert(MyClass);
});
}
This should prevent database locking.

Resources