SQLite. LoadExtension() не загружает модуль mod_spatialite.dll

Привет!

Задача: Необходимо вытянуть геометрию из пространственной БД SQLite на Spatialite в приложении на C# (WPF .NetFramework 4.8). Для этого я выполняю команду SELECT AsText(geometry) к записям базы данных.

В чем проблема: Для того что бы выполнить AsText() нужно подключить модуль Spatialite к SQLite через LoadExtension(), что у меня и не получается.

Пытался через connection.LoadExtinsion("mod_spatialite") Ошибка: System.Data.SQLite.SQLiteException: "SQL logic error Не найден указанный модуль." (хотя модуль есть в папке с приложением, также пробовал указывать путь к нему - проблема не уходит)

Пытался через command.CommandText = "SELECT load_extension(\'mod_spatialite\')"; Ошибка: System.Data.SQLite.SQLiteException: "SQL logic error not authorized" (хотя connection.EnableExtensions(true); прописан, и в sqlite3.exe, о котором в P.S. написано, ошибок не возникает)

    private void test()
        {
            var connectionStr = new SQLiteConnectionStringBuilder()
            {
                DataSource = "polygonSpat.sqlite"
            }.ToString();
            using (var connection = new SQLiteConnection(connectionStr))
            {
                connection.Open();
                var command = connection.CreateCommand();
                connection.EnableExtensions(true);
                connection.LoadExtension("mod_spatialite.dll");
                //command.CommandText = "SELECT load_extension(\'mod_spatialite\')";
                //command.ExecuteNonQuery();

                command.CommandText = "select AsText(geometry) from kek ";

                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine(reader[0]);
                    }
                }
            }
        }

Пробовал как с помощью System.Data.SQLite, так и с помощью Microsoft.Data.Sqlite.

P.S. Скачал отсюда spatialite-loadable-modules-5.0.0-win-amd64.7z, в котором есть sqlite3.exe, который загружает mod_spatialite с помощью SELECT load_extension(\'mod_spatialite\') без проблем и выполняет AsText(). Там же брал spatialite_gui, который работает без проблем.

P.P.S. Пытался собрать сам по этой инструкции, но MSYS2 не стал обновляться, а без обновлений он работать не захотел. Также надо будет запускать мое приложение на других ПК, а каждый раз проводить сборку библиотек на других ПК не хочется, поэтому такой вариант не подходит, однако, может собирать надо один раз... В свою очередь spatial_gui доказывает, что должно быть все проще.

P.P.P.S. Нет метки spatialite, что расстраивает. [UPD: Метка есть)]


Ответы (1 шт):

Автор решения: Николай Смирнов

Спустя несколько дней решение было найдено (не мной, а гением)!!
В общем более подробно можно почитать тут.
Если вкратце, то необходимо в переменной среды PATH прописать путь до директории с модулями Spatialite для SQLite.
Так же приведу пример кода, в котором PATH подменяется только для процесса приложения. В примере mod_spatialite.dll лежит в папке с программой, однако, его можно положить в любое другое место (не проверял с кириллицей в пути).
Использовался NuGet пакет Microsoft.Data.Sqlite на WPF .NetFramework 4.8.

    private void test()
        {
            var connection = new SqliteConnection(@"Data Source=polygonSpat.sqlite");
            connection.Open();
            //Получаем путь до директории с модулями SQLite. В данном случае была взята директория, в которой находится приложение
            string modDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            //Получаем переменную среды path и меняем ее
            string path = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine) + ";" + modDirectory;
            Environment.SetEnvironmentVariable("Path", path, EnvironmentVariableTarget.Process);

            //Загружаем модуль
            connection.LoadExtension("mod_spatialite");

            var command = connection.CreateCommand();
            //Пишем любую команду Spatialite
            command.CommandText =
            @"
                SELECT AsText(geometry) from polygonspat
            ";

            //Работает!
            Tb1.Text = (string)command.ExecuteScalar();
        }

P.S. Если у вас будет возникать ошибка: "...не является win32 приложением", то необходимо зайти в свойства проекта->сборка, там нужно снять галочку "предпочтительна 32-разрядная версия".

→ Ссылка