.netpostgresqltestingpostgisnettopologysuite

PostGis + EF + NetTopologySuite exception writing derived type to db


I am working on a NET 8 app using EF to connect to a Postgres/PostGis database. I have an entity that has a Geometry? datatype (which is the base of Polygon and Point) where I will store either of the derived types. We have an event driven domain, so I actually wrote a projection to persist the existing events into the database, and all this works fine. I can store both polygons and point with no issue.

I am now working on writing tests for the application level logic. I am using Testcontainers.Postgres to run the postgis/postgis:latest image with the postgis and hstore extensions installed. The test using the same DbContext as the projections. However, when my test attempts to create a new record, I get an exception when saving changes to the db. In the case of storing a Polygon type in the Geometry? property, the exception is

System.InvalidCastException : Writing values of 'NetTopologySuite.Geometries.Polygon' is not supported for parameters having NpgsqlDbType 'Geometry'.

When I try to store a new record with a null Geometry? value, I still get this exception:

System.InvalidCastException : Writing is not supported for parameters having NpgsqlDbType 'Geometry'.

So I know the database is set correctly and the DbContext/EF is configured correctly as the projection has no issue. The biggest unknown in the Testcontainer Postgres instance I'm using. But that's running the same image that I run the projection on. I can't figure out what to check now. Any ideas?


Solution

  • There was apparently a change to the way the connetions/type registration works in NpqSql 7. So if you're running 7 or 8, this can happen. It's suggested to use their new NpgsqlDataSourceBuilder. This fixed the issue for me:

     var dataSourceBuilder = new NpgsqlDataSourceBuilder(database.GetConnectionString());
     dataSourceBuilder.UseNetTopologySuite();
     var dataSource = dataSourceBuilder.Build();
    
     services.AddDbContext<ApplicationDbContext>(options =>
     {
         options.UseNpgsql(dataSource, o =>
         {
             o.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName);
             o.MigrationsHistoryTable(schemaService.MigrationsTableName, schemaService.Name);
             o.UseNetTopologySuite();
         });
     });