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-разрядная версия".