CannotOpen exception when trying to reopen same database - sqlite

I'm trying to close a current SQLite connection and reopen a new one.
But sometimes, it's actually the same one (DB name is based on my user ID after login).
This fails with the below exception:
SQLite.SQLiteException occurred
_HResult=-2146233088
_message=Could not open database file: one.sql (CannotOpen)
HResult=-2146233088
Message=Could not open database file: one.sql (CannotOpen)
Source=Cirrious.MvvmCross.Plugins.Sqlite.WindowsPhone
StackTrace:
at SQLite.SQLiteConnection..ctor(String databasePath, Boolean storeDateTimeAsTicks)
InnerException:
To test, I've modified N-10-KittensDb, with the below code:
public DataService(ISQLiteConnectionFactory factory)
{
using (_connection = factory.Create("one.sql"))
{
_connection.CreateTable<Kitten>();
}
using (_connection = factory.Create("one.sql"))
{
_connection.CreateTable<Kitten>();
}
}
Why it would fail on the second using with above exception?
I've already tried calling Close(), Dispose() manually, settting connection var to null and calling GC.Collect, but nothing seems to fix this.
If I close the program and restart new, it works fine.
Looks like the file is in use or similar...
I've debugged until before the SQLlite3 code, and this line in the SQLiteConnection constructor:
var r = SQLite3.Open(DatabasePath, out handle);
is the one returning CannotOpen.
Any idea that could help me pass this, aside from closing the app?
Closing the app could be a possibility, but looks like a to strong solution, as my user is just pressing the "log-out" button.

Related

JavaFX - Handle Exceptions in one place

I am working on JavaFX application and I want to know if there is a way to handle exceptions in one place.
I am doing inserts into database. And when an insert fails, I get an SQLException.
So, is it possible to handle all SQLExceptions (for all inserts) in one place?
I'm aware of:
Thread.setDefaultUncaughtExceptionHandler(...);
But this is probably not the way to go?
It is bad practice to call any code that executes your SQL query (or any other business logic that may take long to execute) directly in the JavaFX application Thread. (I've observed that under Windows JavaFX applications crash without even printing a stacktrace when an uncaught exeption is thrown in the application thread.)
I would suggest to call your SQL-related code using an javafx.concurrent.Task.
Using the setOnFailed() method you can have code invoked whenever an Execption is thrown. There you can look for the type of exception and call any method that handles your SQLException.
Task<SOME_TYPE> mySqlTask = new Task<>() {
#Override
protected SOME_TYPE call() throws Exception {
... // do sql stuff
return mySqlResult; // or null if not needed
}
};
mySqlTask.setOnFailed(event -> {
Throwable exception = mySqlTask.getException();
if (exception instanceof SQLException) {
// call code that handles the sql exception
}
});
// start the task in a separate thread (or better use an Executor)
new Thread(mySqlTask).start();
By the way, I don't think that using Thread.setDefaultUncaughtExceptionHandler(...); is the way to go neither.

Azure documentDB - id conflicts not throwing exception

I am writing a simple API that posts a json document to a single collection in DocumentDB. What is strange, is that I get no exception or indication of error when I try to add a document with the same id more than once.
public static async Task<ResourceResponse<Document>> CreateDocument(Database database, DocumentCollection collection, object obj)
{
try
{
Uri collUri = UriFactory.CreateDocumentCollectionUri(database.Id, collection.Id);
return await client.CreateDocumentAsync(collUri, obj, null, true);
}
catch (DocumentClientException e)
{
// nothing is ever caught...
}
}
The behavior I see is that the first document saves. I can see it in the document explorer. Then if I change data and keep the same id, the code appears to work, but the updated document does not actually get saved, however I dont get an exception as expected. Am I wrong to think there should be an exception here?
In the event of a conflict, DocumentDB throws a Microsoft.Azure.Documents.DocumentClientException with the message: {"Errors":["Resource with specified id or name already exists"]}.
The reason (most likely) you are not seeing the exception is that the code you have runs asynchronously. In other words, your code may be ending execution before the result of the create operation has returned. You can resolve the async method simply by calling .Result.

nhibernate transactions and unit testing

I've got a piece of code that looks like this:
public void Foo(int userId)
{
try {
using (var tran = NHibernateSession.Current.BeginTransaction())
{
var user = _userRepository.Get(userId);
user.Address = "some new fake user address";
_userRepository.Save(user);
Validate();
tran.Commit();
}
}
catch (Exception) {
logger.Error("log error and don't throw")
}
}
private void Validate()
{
throw new Exception();
}
And I'd like to unit test if validations ware made correctly. I use nunit and and SQLLite database for testing. Here is test code:
protected override void When()
{
base.When();
ownerOfFooMethod.Foo(1);
Session.Flush();
Session.Clear();
}
[Test]
public void FooTest()
{
var fakeUser = userRepository.GetUserById(1);
fakeUser.Address.ShouldNotEqual("some new fake user address");
}
My test fails.
While I'm debugging I can see that exception is thrown, Commit has not been called. But my user still has "some new fake user address" in Address property, although I was expecting that it will be rollbacked.
While I'm looking in nhibernate profiler I can see begin transaction statement, but it is not followed neither by commit nor by rollback.
What is more, even if I put there try-catch block and do Rollback explicitly in catch, my test still fails.
I assume, that there is some problem in testing environment, but everything seems fine for me.
Any ideas?
EDIT: I've added important try-catch block (at the beginning I've simplified code too much).
If the exception occurs before NH has flushed the change to the database, and if you then keep using that session without evicting/clearing the object and a flush occurs later for some reason, the change will still be persisted, since the object is still dirty according to NHibernate. When rolling back a transaction you should immediately close the session to avoid this kind of problem.
Another way to put it: A rollback will not rollback in-memory changes you've made to persistent entities.
Also, if the session is a regular session, that call to Save() isn't needed, since the instance is already tracked by NH.

Can I rely on the using statement to close my MySQL connections?

I have an ASP.NET website that uses mysql as it's database. I notice there are a lot of connections "sleeping" when I show a full process list. Today we had some errors "The timeout period elapsed prior to obtaining a connection from the pool.". If the processes are "sleeping" then are they still open from the code? All MySQL connections in the code are in using statements. Can I rely on the using statement to properly close connections?
Edit Code:
I am using this class to create my connection:
public class DbAccess
{
public static MySqlConnection OpenConnection(string connectionStringName)
{
string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
if (string.IsNullOrEmpty(connectionString))
{
throw new ArgumentException("Connection string " + connectionStringName + " does not exist.");
}
MySqlConnection connection = new MySqlConnection(connectionString);
connection.Open();
return connection;
}
}
Then I am calling it like this:
using (MySqlConnection connection = DbAccess.OpenConnection(connectionString))
{
//Code Here
}
Some additional info: Resetting MySql did not make the errors go away, but resetting my app pool did..
C# using blocks are guaranteed to call the .Dispose() method of the object, even if an exception is thrown. That means it's safe, as long as your provider uses the .Dispose() method to close the connection. Looking in the documentation for that type, I see this excerpt (down in section 25.2.3.3.5):
From Open to Closed, using either the Close method or the Dispose method of the connection object.
This tells me you can close the connection via the Dispose method, and so a using block should be all you need.
hope this could be of any help: MySqlConnection really not close
and
Using MySQLConnection in C# does not close properly
and this one
http://social.msdn.microsoft.com/Forums/en/adodotnetdataproviders/thread/c57c0432-c27b-45ab-81ca-b2df76c911ef
yes, absolutely.
using (MySqlConnection connection = DbAccess.OpenConnection(connectionString))
{
//Code Here
}
is exactly the same as
MySqlConnection connection = null
try
{
connection = DbAccess.OpenConnection(connectionString)
//Code Here
}
finally
{
if (connection is IDisposable)
connection.Dispose
}
provided the MySqlConnection class implements IDisposable, then it'll get cleaned up properly. If you need to call another methos, such as close instead of or as well as, then consider the more verbose syntax above and add the method in the finally.

ASP.NET lock() doesn't work

i try to put a lock to a static string object to access to cache,, the lock() block executes in my local,but whenever i deploy it to the server, it locks forever. i write every single step to event log to see the process and lock(object) just causes the deadlock on the server. The command right after lock() is never executed as the i dont see an entry in the event log.
below is the code:
public static string CacheSyncObject = "CacheSync";
public static DataView GetUsers()
{
DataTable dtUsers = null;
if (HttpContext.Current.Cache["dtUsers"] != null)
{
Global.eventLogger.Write(String.Format("GetUsers() cache hit: {0}",dtUsers.Rows.Count));
return (HttpContext.Current.Cache["dtUsers"] as DataTable).Copy().DefaultView;
}
Global.eventLogger.Write("GetUsers() cache miss");
lock (CacheSyncObject)
{
Global.eventLogger.Write("GetUsers() locked SyncObject");
if (HttpContext.Current.Cache["dtUsers"] != null)
{
Global.eventLogger.Write("GetUsers() opps, another thread filled the cache, release lock");
return (HttpContext.Current.Cache["dtUsers"] as DataTable).Copy().DefaultView;
}
Global.eventLogger.Write("GetUsers() locked SyncObject"); ==> this is never written to the log, so which means to me that, lock() never executes.
You're locking on a string, which is a generally bad idea in .NET due to interning. The .NET runtime actually stores all identical literal strings only once, so you have little control over who sees a specific string.
I'm not sure how the ASP.NET runtime handles this, but the regular .NET runtime actually uses interning for the entire process which means that interned strings are shared even between different AppDomains. Thus you could be deadlocking between different instances of you method.
What happens if you use:
public static object CacheSyncObject = new object();

Resources