Search code examples
c#entity-framework-coregeojson.net-6.0nettopologysuite

expected type was 'NetTopologySuite.Geometries.Point' but the actual type was 'GeoJSON.Net.Geometry.Point'


When I uncomment this:

/*.Include(r => r.Establishment)*/

from this:

public bool ReIndexVeganItemEstablishments(
    VepoContext context
)
{
    _searchService.DeleteIndicies(SearchService.SearchIndexMappings[typeof(VeganItemEstablishmentSearchDto)]);
    _searchService.CreateIdx<VeganItemEstablishmentSearchDto>();

    var allVeganItemEstablishmentsArray = allVeganItemEstablishments.ToArray();
    if (allVeganItemEstablishmentsArray.Any())
    {
        var allItems = allVeganItemEstablishments/*.Include(r => r.Establishment)*/.ToArray();
        var searchResults = allItems.Select(item => {
            var toReturn = _mapper.Map<VeganItemEstablishmentSearchDto>(item);
            return toReturn;
        });
        _searchService.Index(searchResults.ToArray());
    }
    return true;
}

I get:

Exception has occurred: CLR/System.InvalidOperationException An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll: 'An error occurred while reading a database value for property 'Establishment.Location'. The expected type was 'NetTopologySuite.Geometries.Point' but the actual value was of type 'GeoJSON.Net.Geometry.Point'.' Inner exceptions found, see $exception in variables window for more details. Innermost exception System.InvalidCastException : Can't cast database type public.geometry to Point at Npgsql.Internal.TypeHandling.NpgsqlTypeHandler.ReadCustom[TAny](NpgsqlReadBuffer buf, Int32 len, Boolean async, FieldDescription fieldDescription)
at Npgsql.Internal.TypeHandling.NpgsqlTypeHandler.Read[TAny](NpgsqlReadBuffer buf, Int32 len, FieldDescription fieldDescription) at Npgsql.NpgsqlDataReader.GetFieldValue[T](Int32 ordinal)

The model:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using NetTopologySuite.Geometries;

namespace Vepo.Domain
{
    [Serializable]
    public class Establishment : CreatedBySomeone
    {
        [Required]
        public string Name { get; set; }
        [Required]
        public string PlaceId { get; set; }
        [Required]
        public string Street { get; set; }
        public string Suburb { get; set; }
        public string City { get; set; }
        public string StreetNumber { get; set; }
        
        [Column(TypeName="geometry (point)")]
        public Point Location { get; set; }

    }
}

The db insertion code:

        if (entity.Establishment != null) {
            establishments.AddIfNotExists<Establishment>(
                entity.Establishment, 
                x => x.PlaceId == entity.Establishment.PlaceId);
            await context.SaveChangesAsync();
            establishmentId = establishments.Single(a => a.PlaceId == entity.Establishment.PlaceId).Id;
            toReturnEstablishment.Id = (int)establishmentId;
        }

    public static EntityEntry<T> AddIfNotExists<T>(this DbSet<T> dbSet, T entity, Expression<Func<T, bool>> predicate = null) where T : class
    {
        var exists = predicate != null ? dbSet.Any(predicate) : dbSet.Any();
        return exists ? null : dbSet.Add(entity);
    }

OnModelCreating:

    modelBuilder.Entity<Establishment>(establishment =>
    {
        establishment.HasIndex("PlaceId").IsUnique();
        establishment.Property(u => u.CreatedDate)
            .HasDefaultValueSql("CURRENT_TIMESTAMP"); 
        establishment.Property(u => u.UpdatedDate)
            .HasDefaultValueSql("CURRENT_TIMESTAMP");
        establishment.HasOne(q => q.UpdatedBy)
            .WithMany()
            .HasForeignKey(k => k.UpdatedById);
        establishment.HasOne(q => q.CreatedBy)
            .WithMany()
            .HasForeignKey(k => k.CreatedById);
    });

Any idea why Include(r => r.Establishment) gets type GeoJSON.Net.Geometry.Point?


Solution

  • I assume that you have a configuration error. Have a look at https://www.npgsql.org/doc/types/nts.html