Péter Aradi
Péter Aradi

Reputation: 390

Unable to load DLL 'e_sqlite3': The specified module could not be found

I have a Xamarin Forms solution. I added sqlite-net-pcl as reference to all projects. It works fine on Android but crashes on Windows 8.1 and Windows Phone 8.1. I have an IOS project but I don't have OSX at the moment to try it.

I use this in the Windows projects to access the database:

using System.IO;
using SQLite;
using Xamarin.Forms;
using HelloXamarin.Windows;
using Windows.Storage;

[assembly: Dependency(typeof(SQLiteDb))]

namespace HelloXamarin.Windows
{
   public class SQLiteDb : ISQLiteDb
    {
        public SQLiteAsyncConnection GetConnection(string databaseName)
        {
            var documentsPath = ApplicationData.Current.LocalFolder.Path;
            var path = Path.Combine(documentsPath, databaseName);
            return new SQLiteAsyncConnection(path);
        }
    }
}

Here are my references:

References

I get this exception when trying to access the database:

The type initializer for 'SQLite.SQLiteConnection' threw an exception.

Unable to load DLL 'e_sqlite3': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

I have no idea how to solve this, please help me!

The whole solution is available on GitHub: https://github.com/apspot/HelloXamarin

Upvotes: 9

Views: 18087

Answers (5)

Slack Groverglow
Slack Groverglow

Reputation: 856

I believe the root of this issue is that the program cannot load the e_sqlite3.dll file. I think all the issues here are in one way or another resolving this by either moving the file or updating the PATH and they all seem to work.

For reference, If you include Microsoft.Data.Sqlite it should download the transitive package sqlitepclraw.lib.e_sqlite3 which contains the file under %nuget packages%\sqlitepclraw.lib.e_sqlite3\%version%\runtimes\%platform%

Upvotes: 0

tuke307
tuke307

Reputation: 430

For me, it worked by adding the e_sqlite3 bundle to the executable project

Upvotes: 9

Moumit
Moumit

Reputation: 9630

By this time the issue is still open. So before they come with some solid fix, you can use this work around, to solve the issue for now.

Add one helper class

using System;
using System.Diagnostics;
using System.IO;

namespace SQLitePCL
{
    public class NativeLibraryHack
    {
        public static bool Hacked { get; private set; }

        public static bool DoHack()
        {
            if (Hacked) return true;

            try
            {
                const string runtimeFolderName = "/runtimes";

                var destinationPath = typeof(SQLitePCL.raw).Assembly.Location
                    .Replace("\\", "/");
                var destinationLength = destinationPath.LastIndexOf("/", StringComparison.OrdinalIgnoreCase);
                var destinationDirectory = destinationPath.Substring(0, destinationLength) + runtimeFolderName;

                var sourcePath = new Uri(typeof(SQLitePCL.raw).Assembly.CodeBase)
                    .AbsolutePath;
                var sourceLength = sourcePath.LastIndexOf("/", StringComparison.OrdinalIgnoreCase);
                var sourceDirectory = sourcePath.Substring(0, sourceLength) + runtimeFolderName;

                if (Directory.Exists(sourceDirectory))
                    CopyFilesRecursively(new DirectoryInfo(sourceDirectory), new DirectoryInfo(destinationDirectory));
            }
            catch (Exception ex)
            {
                //Ignore Exception
                Debug.WriteLine(ex.Message);
                return false;
            }

            return (Hacked = true);
        }

        private static void CopyFilesRecursively(
            DirectoryInfo source,
            DirectoryInfo target
        )
        {
            foreach (var dir in source.GetDirectories())
                CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));

            foreach (var file in source.GetFiles())
            {
                try
                {
                    var destinationFile = Path.Combine(target.FullName, file.Name);
                    if (!File.Exists(destinationFile))
                        file.CopyTo(destinationFile);
                }
                catch (Exception ex)
                {
                    //Ignore Exception
                    Debug.WriteLine(ex.Message);
                }
            }
        }
    }
}

And add the hack before your db migration script, I am using web api 2 so i did on RouteConfig.RegisterRoutes

    NativeLibraryHack.DoHack();

    using (KSDBContext db = new KSDBContext())
    {
        db.Database.Migrate();                 
    }

Upvotes: 3

MelOS
MelOS

Reputation: 653

Try referencing Visual C++ 2015 Runtime for Universal Windows Platform Apps. That sorted it out for me.

  1. Go to References
  2. Add Reference
  3. Extensions.
  4. Check"Visual C++ 2015 Runtime for Universal Windows Platform Apps"
  5. OK

Upvotes: 0

Adam
Adam

Reputation: 16199

You need to add the SQLite Extensions.

  1. Go to Tools > Extensions and Updates
  2. Go to Online, then search for SQLite.
  3. Download SQLite for Windows Runtime

enter image description here

  1. In your Windows Project, Add Reference and ensure you add the extension.

enter image description here

Also remove Microsoft.VCLibs from your references.

Upvotes: 1

Related Questions