dotnet / EntityFramework.Docs

Documentation for Entity Framework Core and Entity Framework 6
https://docs.microsoft.com/ef/
Creative Commons Attribution 4.0 International
1.63k stars 1.96k forks source link

Document using NetTopologySuite with spatialite on Docker #3443

Open jcrawfor74 opened 3 years ago

jcrawfor74 commented 3 years ago

SQLite Error 1: 'mod_spatialite.so: cannot open shared object

Hi,

I am getting the following error.

I have been researching a solution and read through the various sqlite ef documentation but with no luck fixing the issue.

The scenario;

This code is working on windows. As a docker image hosted on docker desktop (windows), it is throwing the error above. On an Ubuntu Linux box (20.04.3) and this also crashes but differently.

The code

On the docker image it is crashing on the database creation step. On the Linux box it crashes on the EF data insertion, (if I remove the NetTopologySuite on the EntityFramework OnConfiguringI was able to get it too run successfully).

I don't, particularly care about getting it working on the linux box (just using it for trouble shooting), but I am attempting to host this architecture stack as a docker image on an AWS ECS container, and I need the Spatial Data for my solution.

I have followed the help from here - https://docs.microsoft.com/en-us/ef/core/providers/sqlite/spatial I have tried various SQLitePCLRaw providers but I am not familiar with how to use these to fix the issue. Any pointers on what I am doing wrong would be greatly appreciated.

Full code sample here on github. https://github.com/jcrawfor74/homedev-webapi-sqlite

provider and version information

EF Core version: 5.0.10 Database provider: Microsoft.EntityFrameworkCore.Sqlite.Core Target framework: (e.g. .NET 5.0) Operating system: Linux Docker Image IDE: VS Code

jcrawfor74 commented 3 years ago

Hi,

I have managed to fix my own issue and hope to help anyone who also hits this error in the future

Fix for Error _modspatialite.so: cannot open shared object file: No such file or directory'.

This error was due to the need to install

Items to install on linux To run on linux successfully you need to install the following;

RUN apt-get update \
    && apt-get install -y libsqlite3-mod-spatialite \
    && apt-get install -y libspatialite-dev

The libspatialite-dev solves a different crash that I was getting after installing libsqlite3-mod-spatialite

Package Reference problems There is a real issue in trying to get this to work nicely. All of my Sqlite package references are contained in the DataAccess Library.

Package References For Windows

<ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.10" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="5.0.10" />
</ItemGroup>

Package References for Linux

<ItemGroup>    
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.10" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="5.0.10" />
    <PackageReference Include="SQLitePCLRaw.bundle_sqlite3" Version="2.0.6" />
</ItemGroup>

Note: These package references below can be run on Linux and windows without causing issues, but the smallest set of references would be those above for each platform.

    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.10" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.10" />

This took me a while to sort out. So now if I want to run this on different platforms, i.e. debug on windows and then deploy to a docker image, I need conditional package references based upon the OS the code is running on!!?

After all of the above it breaks down to the SQLitePCLRaw library being optionally required on Linux

with help from https://blog.magnusmontin.net/2018/11/05/platform-conditional-compilation-in-net-core/ I came up with this..

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <!-- https://blog.magnusmontin.net/2018/11/05/platform-conditional-compilation-in-net-core/ -->
    <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.10" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.10" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="5.0.10" />
    <PackageReference Include="SQLitePCLRaw.bundle_sqlite3" Version="2.0.6" Condition="'$(IsLinux)'=='true'" />
  </ItemGroup>
    ...
</Project>

With the Linux reference only being loaded when running on Linux.

So now I can build and run ;

sorry if I wasted anyone's time, but this was tricky to sort out.

ErikEJ commented 3 years ago

@bricelam doc improvement?

jcrawfor74 commented 3 years ago

P.S. the latest commit on the linked public github repo contains a working sample of all of the above, with a basic .net core webapi (using an AWS Serverless Lambda Stack template) in case that helps to clarify anything I may have incorrectly described above. :-) https://github.com/jcrawfor74/homedev-webapi-sqlite

bricelam commented 3 years ago

I discussed all this a while ago in https://github.com/ericsink/SQLitePCL.raw/discussions/429#discussioncomment-1066137

It's probably worth adding a bit more to the docs.

vkx86 commented 3 years ago

Hi,

I have managed to fix my own issue and hope to help anyone who also hits this error in the future

Fix for Error _modspatialite.so: cannot open shared object file: No such file or directory'.

I'd faced same problem in similar scenario - your investigation was very helpful. In my case I found that: On Linux/Docker the dependencies are libsqlite3-dev and libsqlite3-mod-spatialite. If no SQLitePCLRaw.bundle_sqlite3 nuget referenced in linux/docker - the app crashes "silently". Conditional inclusion of SQLitePCLRaw.bundle_sqlite3 package didn't worked in my case - it was not included in build when ran in Docker. Neither Condition=" '$(OS)' == 'Unix' " worked, so I left it unconditional and it works both on Windows and in Docker.