DB4o database DatabaseFileLockedException - database

I would like to access the same db file from different programs in parallel. All programs are running on the same VM. Here is the code I use:
private ObjectContainer db;
public DatabaseManager(String dbName) {
ObjectServer server = Db4oClientServer.openServer(Db4oClientServer
.newServerConfiguration(), dbName, 0);
try {
db = server.openClient();
// Do something with this client, or open more clients
} catch(Exception ex) {
ex.printStackTrace();
}
}
When I run the second program I get DatabaseFileLockedException. How to use this db in parallel?

Only one db4o instance can access the database file at the same time. If you try to reopen it while a object container has it open you will get this DatabaseFileLockedException.
Within the same JVM instance you can open new session containers like this:
ObjectContainer rootContainer = // the one you've opened the file with
ObjectContainer session = rootContainer.ext().openSession()
With your code you also can use the .openClient() method to do the same. However you actually don't need the client server stuff as long as you're in the same JVM instance. You can use the stuff above with a regular embedded object container.
In case you need to access the same database from multiple databases, then you need a full blown client-server setup.

Related

Copy/Cache Azure database locally for offline use.

I have a piece of software that connects to an Azure database to gather formulas for several varieties of colors to allow the user to follow a recipe to create their own product.
Basically there is just one big database pull when the application launches, that pulls down all the formulas, and from there the user can simply use, modify, or even delete the formulas as they wish.
The problem is that where this software is used, there are seldom constant internet connections, and the application so far is simply designed to shutdown if there isn't one present.
I am looking for a solution for being able to allow the application to BOTH connect to the database on application startup(If a connection is present) and save a copy locally, or if no connection is present, check for a locally saved copy to work with.
I have looked everywhere, but have been unable to find any methods to "programmatically" retrieve the pertinent(or all, if necessary) data, and either export it to a local file, or cache it somehow for offline use.
Any suggestions?
You don't mention what kind of technology you're using on the client side, and if you require access to a database on the client or just the data - but regardless there are several ways to do this.
Azure Mobile apps have a quickstart which will implements an Azure SQL <-> SQL Lite (mobile) database sync framework (table controllers on the server side). This lets you use libraries on the mobile side to use the local db for getting its data, and when you know you're online you can sync to/from the server. This is quite sophisticated and probably gives you more than just the caching that you're looking for.
I've used two other strategies for caching - one for HTML/javascript based applications (phonegap/cordova) and the other for Xamarin c# apps on iOS and Android. I'm assuming if it's a standard windows desktop app you know how to persist data so you can use whatever kind of cache/file system/db you like.
JavaScript/html - use the html5 localStorage functions to store the JSON output of the web server calls you're making. This is really easy then to abstract, where your app before is making an ajax call to the server to get some data, instead move that to a "liveorcache" class, which can determine whether to go to the server or just use the local storage. Code snippet for saving/loading json in localstorage below:
$scope.saveFixtures = function () {
localStorage["fixtures"] = JSON.stringify($scope.fixtures);
};
$scope.loadFixtures = function () {
if (localStorage["fixtures"] != undefined) {
$scope.fixtures = JSON.parse(localStorage["fixtures"]);
}
};
If you're writing your app in Xamarin you can do the same kind of thing, but using a PCL library - I used "PCLStorage" which works on Android and iOS. Same strategy though, in my code I just write the JSON data to a file with an appropriate filename, but usually wrap the object in another object that contains the cache write date/time. You then serialise the object to the file - something like below.
public class CacheProvider
{
public static async Task<CacheModel> ReadCache<T>(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder cache = await rootFolder.CreateFolderAsync("sportenzaCache", CreationCollisionOption.OpenIfExists);
try
{
IFile file = await cache.GetFileAsync(filename);
var data = await file.ReadAllTextAsync();
return JsonConvert.DeserializeObject<T>(data) as CacheModel;
}
catch(FileNotFoundException ex)
{
return null;
}
}
public static async void WriteCache<T>(string filename, CacheModel data)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder cache = await rootFolder.CreateFolderAsync("sportenzaCache", CreationCollisionOption.OpenIfExists);
IFile file = await cache.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
if (file != null)
{
data.CacheCreated = DateTime.Now;
string json = JsonConvert.SerializeObject(data);
await file.WriteAllTextAsync(json);
}
}
public static async void DeleteCache(string filename)
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder cache = await rootFolder.CreateFolderAsync("sportenzaCache", CreationCollisionOption.OpenIfExists);
IFile file = await cache.GetFileAsync(filename);
if (file != null)
await file.DeleteAsync();
}
}

Create persistent Sqlite db in Windows phone 8

I am trying my hands on Windows phone 8 applications and I am stuck into a weird situation here. I am using sqlite in order to create sqlite db and add values into the database. I am able to create the database and add the values in the database successfully but I am having a weird situation here.
Everytime I close the emulator and start the project again the database gets created again which should not be happening because I created the db the very first time I run the application.
Does anybody know why, and how I can prevent it from recreating the database each time?
public string DB_PATH = Path.Combine(Path.Combine(ApplicationData.Current.LocalFolder.Path, "aa.sqlite"));
private SQLiteConnection dtCon;
public MainPage()
{
InitializeComponent();
CreateDatabase();
dtCon = new SQLiteConnection(DB_PATH);
var tp = dtCon.Query<Contacts>("select * from contacts").ToList();
}
private async void CreateDatabase()
{
bool isDatabaseExisting = false;
//Checking if database already exists
try
{
Windows.Storage.StorageFile storagefile = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("aa.sqlite");
isDatabaseExisting = true;
}
catch
{
isDatabaseExisting = false;
}
//if not exists then creating database
if (!isDatabaseExisting)
{
String str = System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "sqlite.db");
AddDataToDB(DB_PATH);
}
}
private void AddDataToDB(string str)
{
// Create the database connection.
dtCon = new SQLiteConnection(str);
// Create the table Task, if it doesn't exist.
dtCon.CreateTable<Contacts>();
Contacts oContacts = new Contacts();
oContacts.Name = "dfgdf";
oContacts.Detail = "asdfsf";
dtCon.Insert(oContacts);
}
I'm pretty sure when you close your emulator and restart, you're basically just uninstalling the application. Which is why your files or not there anymore -- as it looks like you're storing your data in isolated storage. I do not know if there is anyway around this.
You can buy a very cheap Windows 8/8.1 Phone and the files will persist until you manually uninstall the test application.
As #Chubosaurus says, closing and re-opening the emulator will remove all the apps. You can generally keep it running as long as you want and keep re-deploying your app to the emulator (although obviously rebooting the host PC will kill it).
You can save and restore the data from your emulator image via the ISETool command. See more here
Try adding Console.WriteLine("True"); and Console.WriteLine("False"); into the expected places after checking isDatabaseExisting to see/understand what the code path really is.

Can't create sqlite db on production machine

I have a program that works correctly on my computer in Debug mode.
When my program start he create a Sqlite data base file if not exists.
This is ok on my computer.
I create a setup version for production version. The program setup is ok.
But when I start the program (.exe) my db file is not created.
This is the connection string I used :
static string dbDirectopry = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
static string dbName = "MySqliteDb.db";
static string Connexion = Path.Combine(dbDirectopry, #"MySociety\MyApplication\" + dbName);
Hi thanks for your help,
this is the code that create db.
public static void CreateDb(string path)
{
SqLiteHelper sqlite = new SqLiteHelper(path);
try
{
User.CreateTable();
}
catch (Exception e)
{
throw e;
}
}
Normaly if the file doesn't exists he is automaticaly created.
If I try my application in Debug mode with Visual Studio my db is created and I can write into.
But when I deploy my application it doesn't work anymore.
My problem is is there any special directory (for windows) to create de db file?

QSqlDatabase Connecting to Multiple Databases

I am having issues attempting to connect to two different databases in one Qt Application. I have my information database that stores all the information collected by the application and the new Log database which allows me to track all the changes that occur to the Application, button presses, screen loads etc, for easy debugging after its release. Separately, the databases work perfectly, but when I try to use both of them, only one will work. I read that this could be because I wasn't naming the connections and obviously only the most recently connected database could use the default connection. However when I give the databases names they wont work at all, isOpen() will return true on both, but as soon as they attempt to execute a query I get the errors
"QSqlQuery::prepare: database not open"
"QSqlError(-1, "Driver not loaded", "Driver not loaded")"
My two database declarations are:
database_location = filepath.append("/logger.sqlite");
logDB = QSqlDatabase::addDatabase("QSQLITE", "LoggerDatabaseConnection");
logDB.setHostName("localhost");
logDB.setDatabaseName(database_location);
for the Logger Database connection and :
database_location = filepath.append("/db.sqlite");
db = QSqlDatabase::addDatabase("QSQLITE", "NormalDB");
db.setHostName("localhost");
db.setDatabaseName(database_location);
Also when I am running the first query on the databases to see if their tables exist I am using
QSqlQuery query("LoggerDatabaseConnection");
and likewise for the normal database, but I am still getting connection issues even after declaring the database connection to run the query on.
The database used for the application is declared as a static QSqlDatabase in a namespace to create a global effect, so everyone can access it, that was a previous programmer, and I created the Log database as Singleton with a private database connection. Like I said both versions of the code work separately but when they are together they are fighting each other. I know there is a huge debate over the proper design of Singleton vs Dependecy Injection, but again the code works separately so I am happy with how it is designed for now. If there is any missing information or if you have any ideas, please let me know. Thank you.
QSqlQuery query("LoggerDatabaseConnection");
The first parameter of the constructor is the query, not the connection name. It will use the default connection since you specified no database object.
Try something like this:
QSqlQuery query1("YourFirstQuery", db);
QSqlQuery query2("YourSecondQuery", logDB);
Important: Also do not forget to open and close the database before / after using it by calls to QSqlDatabase::open() and QSqlDatabase::close().
The correct way to have multiple databases is to not use the pointer returned from the static addConnection method. You should use the connectionName argument:
https://doc.qt.io/qt-5/qsqldatabase.html#addDatabase-1 during initilization and query usage:
example:
void MyClass::initDb(QString dbPath, QString connName)
{
// initial db usage, etc
QSqlDatabase db = QSqlDatabase::addDatabase(YOUR_DRIVER, connName);
db.setDatabaseName(dbPath);
// open it, etc
}
void MyClass::updateThing(QString val, QString name, QString connName)
{
QString q = QString("UPDATE THINGS SET val=%1 WHERE name=%2").arg(val, name);
// add the reference to your database via the connection name
QSqlDatabase db = QSqlDatabase::database(connName);
QSqlQuery query(db);
query.exec(q);
// handle the query normally, etc
}

Create a SQLite database with Monotouch - permission denied

I am trying to create a Sqlite database using Monotouch 3.0.3.4. Everything works fine on the iPhone simulator, but I get the following error on the test iPhone:
DataLayer.CreateDatabase Exception: System.UnauthorizedAccessException: Access to the path "/private/var/mobile/Applications/4B4944BB-EC37-4B0C-980C-1A9B60DACB44/TestApp.app/myDatabase.db3" is denied.
Here is the code I am using:
// creates database and tables if they do not exist.
public void CreateDatabase ()
{
string sql = string.Empty;
string dbFileName = "myDatabase.db3";
try {
if (!File.Exists (dbFileName)) {
// create database
SqliteConnection.CreateFile (dbFileName); //This is where the error occurs
Console.WriteLine ("CreateDatabase: Database created.");
...
}
catch (Exception ex) {
Console.WriteLine ("CreateDatabase Exception: " + ex.ToString ());
}
...
I have also tried specifing the personal folder, but that has no effect. What do I need to do to make sure permissions are correct?
Thanks!
Monotouch 3.0.3.4
That's likely MonoDevelop 3.0.3.4. See About MonoDevelop to get the MonoTouch version.
"/private/var/mobile/Applications/4B4944BB-EC37-4B0C-980C-1A9B60DACB44/TestApp.app/myDatabase.db3"
On devices the applications are signed, so their content can't change (without breaking the signature). As such you're not allowed to change things in the .app directory.
You should create (or copy) the database in the Documents directory and then open the database as read-write.
See the linked article for more details.

Resources