dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.73k stars 3.17k forks source link

Running into Segmentation fault on Ubuntu 20.04.5 LTS when using NetTopology and Sqlite. #29167

Closed Procrastinatorhater closed 2 years ago

Procrastinatorhater commented 2 years ago

I cant seem to use the NetTopology package with Sqlite on newer Ubuntu versions. I have been using Ubuntu 18.04 LTS for some time, but a segmentation fault is preventing me from updating to 20.04 or 22.04.

On the test machines I manually install the following package(s): sudo apt-get install libc6-dev - used by another dependency in production systems, but not required for reproducing issue. sudo apt-get install libsqlite3-mod-spatialite

Without the libsqlite3-mod-spatialite I run into the following exception. AGAIN THIS IS NOT THE ERROR I AM TRYING TO FIX - INCLUDED ONLY FOR FULL DISCLOSURE. ONLY HAPPENS WHEN I DONT MANUALLY INSTALL PACKAGE .

Unhandled exception. Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'mod_spatialite.so: cannot open shared object file: No such file or directory'.
   at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
   at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader()
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteNonQuery()
   at Microsoft.Data.Sqlite.SqliteConnectionExtensions.ExecuteNonQuery(SqliteConnection connection, String commandText, SqliteParameter[] parameters)
   at Microsoft.Data.Sqlite.SqliteConnection.LoadExtensionCore(String file, String proc)
   at Microsoft.Data.Sqlite.SqliteConnection.Open()
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteScalar(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal.SqliteDatabaseCreator.HasTables()
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreated()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()
   at Program.<Main>$(String[] args)
Aborted (core dumped)

Have tested: Ubuntu 18.04 (LTS) - success Ubuntu 20.04 (LTS) - segmentation fault. Ubuntu 22.04 (LTS) - segmenation fault.

No errors, program just exits: https://www.dropbox.com/s/w56t29we7erikhz/SegmentationFault.png?dl=0

I have a simple .Net 6 console project setup for a reproducible test.

Project has the following dependencies defined: Have tried all versions from 5.0.17 to 7.0.0-rc.1.22426.7

 <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-rc.1.22426.7">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.0-rc.1.22426.7" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-rc.1.22426.7" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="7.0.0-rc.1.22426.7" />

    <!-- When testing packages before 6.0 the following is also required -->
    <!--<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.2" /> -->
  </ItemGroup>

Program.cs creates context via helper, ensures schema was created and inserts 50 dummy records into a basic table.

using Microsoft.Data.Sqlite;

string filePath = "database.db";

SqliteConnectionStringBuilder scb = new SqliteConnectionStringBuilder()
{
    Pooling = false,
    DataSource = filePath
};

using (TestDataContext context = LocalContextFactory.CreateContext<TestDataContext>(scb.ConnectionString))
{
    context.Database.EnsureCreated();

    for (int i = 0; i < 50; i++)
    {
        Guid id = Guid.NewGuid();
        context.ObjectData.Add(new ObjectData() { ObjectUniqueId = id, Name = $"{id}" });
    }

    context.SaveChanges();
}

Console.WriteLine("Success"); //never gets here on newer Ubuntu versions. 

Context has 2 entities defined:

using Microsoft.EntityFrameworkCore;

public class TestDataContext : DbContext
{
    public TestDataContext()
    {
    }

    public TestDataContext(DbContextOptions<TestDataContext> options) : base(options)
    {
    }

    public virtual DbSet<ObjectData> ObjectData { get; set; }
    public virtual DbSet<GeometryData> GeometryData { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ObjectData>(x => {
            x.HasKey(e => e.ObjectUniqueId);
            x.Property(p => p.ObjectUniqueId)
                .HasConversion(s => s.ToString(), s => new System.Guid(s));
        });

        modelBuilder.Entity<GeometryData>(x => {
            x.HasKey(e => e.ObjectUniqueId);
            x.Property(p => p.Geometry).HasSrid(4326);
            x.Property(p => p.ObjectUniqueId)
                .HasConversion(s => s.ToString(), s => new System.Guid(s));
        });

        base.OnModelCreating(modelBuilder);
    }
}

And those entities look like so:

using System.ComponentModel.DataAnnotations.Schema;

[Table("geometry_data")]
public class GeometryData
{

    [Column("object_unique_id")]
    public System.Guid ObjectUniqueId { get; set; }

    [Column("geometry_type_id")]
    public System.Int32 GeometryTypeId { get; set; }

    [Column("geometry")]
    public NetTopologySuite.Geometries.Geometry Geometry { get; set; }

}

[Table("object_data")]
public class ObjectData
{

    [Column("object_unique_id")]
    public System.Guid ObjectUniqueId { get; set; }

    [Column("object_name")]
    public string Name { get; set; }
}

I have a helper class for creating a local Sqlite dbContext with NetTopology enabled - This is only used in testing since I dont want to setup DI and bring in additional dependencies in test project:

public static class LocalContextFactory
{
    public static TContext CreateContext<TContext>(string connectionString, bool useNetTopologyProvider = true) where TContext : DbContext
    {
        DbContextOptionsBuilder<TContext> optionsBuilder = new DbContextOptionsBuilder<TContext>();
        optionsBuilder.UseSqlite(connectionString, sqliteDbContextOptionBuilder =>
        {
            if (useNetTopologyProvider)
            {
                sqliteDbContextOptionBuilder.UseNetTopologySuite();
            }
        });

        TContext context = Activator.CreateInstance(typeof(TContext), optionsBuilder.Options) as TContext;

        return context;
    }
}
smitpatel commented 2 years ago

This could be cause for https://github.com/dotnet/efcore/pull/29157 too.

ajcvickers commented 2 years ago

/cc @bricelam

ajcvickers commented 2 years ago

@bricelam I can't find the docs on this.

bricelam commented 2 years ago

Installing SpatiaLite

ajcvickers commented 2 years ago

@Procrastinatorhater See the instructions referenced by @bricelam above for using SpatiaLite in this environment.