4

According to the platform specific notes for Akavache:

.NET 4.5 Desktop (WPF) - You must mark your application as x86, or else you will get a strange runtime error about SQLitePCL_Raw not loading correctly.

Right now I'm just trying to test out Akavache in LINQPad using simple code modeled after the sample code on the Akavache Github page.

async void Main()
{
    BlobCache.ApplicationName = "JonTestApp1";
    var dt = DateTime.Now;
    await BlobCache.UserAccount.InsertObject("Test1", dt);
    var toaster = await BlobCache.UserAccount.GetObject<DateTime>("Test1");
    toaster.Dump();
}

And predictably it is blowing up.

How do I mark my application build target in LINQPad to x86? Using v. 4.53.16, not the AnyCPU build, just the normal beta. I've looked everywhere in the settings and Google but cannot find anything.

Thanks

* Update 1 *

Trying @Joe Albahari 's suggestion. IntPtr.Size is indeed 4. This is the exception I'm getting on the first await line:


System.TypeInitializationException: The type initializer for 'NativeMethods' threw an exception. ---> System.Exception: sqlite3.dll was not loaded.
   at SQLitePCL.SQLite3Provider.NativeMethods..cctor()
   --- End of inner exception stack trace ---
   at SQLitePCL.SQLite3Provider.NativeMethods.sqlite3_open_v2(Byte[] filename, IntPtr& db, Int32 flags, Byte[] vfs)
   at SQLitePCL.SQLite3Provider.SQLitePCL.ISQLite3Provider.sqlite3_open_v2(String filename, IntPtr& db, Int32 flags, String vfs)
   at Akavache.Sqlite3.Internal.SQLiteConnection..ctor(String databasePath, SQLiteOpenFlags openFlags, Boolean storeDateTimeAsTicks)
   at Akavache.Sqlite3.Internal.SQLiteConnection..ctor(String databasePath, Boolean storeDateTimeAsTicks)
   at Akavache.Sqlite3.SQLitePersistentBlobCache..ctor(String databaseFile, IScheduler scheduler)
   at Akavache.Sqlite3.Registrations.c__DisplayClass6.b__2()
   at System.Lazy`1.CreateValue()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Lazy`1.get_Value()
   at Akavache.Sqlite3.Registrations.c__DisplayClass6.b__3()
   at Splat.ModernDependencyResolver.GetService(Type serviceType, String contract) in z:\code\paulcbetts\splat\Splat\ServiceLocation.cs:line 223
   at Splat.DependencyResolverMixins.GetService[T](IDependencyResolver This, String contract) in z:\code\paulcbetts\splat\Splat\ServiceLocation.cs:line 138
   at Akavache.BlobCache.get_UserAccount()
   at UserQuery.d__0.MoveNext() in c:\Users\jcomtois\AppData\Local\Temp\LINQPad\_qizvxzkh\query_rjuuom.cs:line 45

Since I installed Akavache via LINQPad's NuGet, I had to do some searching to find out where sqlite3.dll was. I found about 15 different slqlite3.dll within the Akavache NuGet package (within my AppData/Local/LINQPad/Nuget...) for various builds. I tried copying the one in the x86 folder first to the LINQPad directory, but same error. I then tried copying each of the other of the sqlite3.dll's to the LINQPad folder, but still the same result.

I can't install Visual Studio on this machine so I was hoping there was a way to get this to work with LINQPad.

Jon Comtois
  • 1,774
  • 1
  • 19
  • 29

3 Answers3

2

After being frustrated by this for basically forever, I combed the sqlite3_raw dependency and found this:

private static bool TryLoadFromDirectory(string dllName, string baseDirectory)
{
    /* snip */

    var architecture = IntPtr.Size == 4 ? "x86" : "x64";
    var dllPath = System.IO.Path.Combine(baseDirectory, architecture, dllName);
    if (!System.IO.File.Exists(dllPath))
    {
        return false;
    }

   /* snip - loads the dll */
}

once I moved sqlite3.dll to "{linqpad}\x86\sqlite3.dll", it worked AOK.

rdavisau
  • 875
  • 6
  • 12
  • Your answer got me on the right track to figure out what was going on. I hit a few more snags than you apparently did, so I added a detailed answer of my solution. Thank you for getting me started! – Jon Comtois Apr 29 '15 at 15:49
  • This appears to no longer work, after a few things i'm now up to an `Unable to load DLL 'e_sqlite3'` error – Rhys Bevilaqua Nov 13 '18 at 09:14
1

@rdavisau's answer got me on the right track to finally figuring this out. His solution did not work for me as it was. Akavache 4.1.0 and LINQPad 4.55.03 in this answer.

The source code that helped me was here.

Once I saw that TryLoadFromDirectory was being called with new Uri(AppDomain.CurrentDomain.BaseDirectory).LocalPath) as its location to find the sqlite3.dll, I was able to see where that location was in LINQPad by calling a .Dump() on that line of code.

For me currently, it was C:\ProgramData\LINQPad\Updates40\455\. Which is a little unfortunate, since each time LINQPad auto-updates it will go to a different directory.

So I created an x86 directory in that directory I had just found, then tried putting the sqlite3.dll in there from the NuGet package. I had to go find it from LINQPad's NuGet cache. I determined the correct one for me was found here: C:\Users\jcomtois\AppData\Local\LINQPad\NuGet\akavache.sqlite3\SQLitePCL.raw_basic.0.7.0\build\native\sqlite3_dynamic\winxp\x86\sqlite3.dll.

So now I think I had the proper .dll for my test LINQPad program to work. I ran it and then got prompted with The Program can't start because MSVCR110.dll is missing from your computer. Try reinstalling the program to fix this problem. Ugh. Remember this machine has no Visual Studio installed. I went here and downloaded and installed the redistributables.

I ran my test code again (after doing "Cancel all threads and reset"). Success!

Once this worked, I tried putting the x86 folder with the right sqlite3.dll in the LINQPad install directory, but that did not work. I assumed that was what @rdavisau was referring to in his answer as it was not clear.

Kind of an ordeal to run Akavache in LINQPad, I wish it was easier, but it is possible.

Community
  • 1
  • 1
Jon Comtois
  • 1,774
  • 1
  • 19
  • 29
  • Interesting - when I tested BaseDirectory, I got my LINQPad install directory. I actually tried the fix on two boxes and so I assumed it was the same for everyone. On reflection, I always use the "no-installer" version of LINQPad - might have something to do with it. – rdavisau Apr 29 '15 at 20:20
0

The X86 build of LINQPad always runs your queries in a 32-bit process.

You can verify this by running the following query:

IntPtr.Size

If this returns 4, you're in a 32-bit process.

You mention that your library uses SQLite. If so, the problem might be that the CLR cannot resolve its native DLL. Try copying SQLite's native DLL into the LINQPad folder (you can create a special folder with a copy of LINQPad.exe just for this purpose).

Joe Albahari
  • 28,102
  • 6
  • 74
  • 88
  • I added some updated information to my question. I am in 32-bit process. However, either I'm not copying the right sqlite DLL into my LINQPad folder, or that is not the issue. No luck so far. – Jon Comtois Feb 04 '15 at 14:55