dapper.fastcrud не отображает данные геометрии из postgresql - PullRequest
0 голосов
/ 06 октября 2018

У меня есть пространственные данные в Postgresql.Например, таблица planet_osm_point имеет 2 атрибута:

CREATE TABLE public.planet_osm_point
(
    osm_id bigint,
    way geometry(Point,3857)
)

Если я использую dapper для операций CRUD, все работает нормально.Но если я использую Dapper.fastCRUD, тогда свойство "way" с геометрией всегда равно нулю

Класс OsmPoint:

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

namespace DapperTest
{
    [Table("planet_osm_point")]
    public class OsmPoint
    {
        [Column("osm_id")]
        public long OsmId { get; set; }

        [Column("way")]
        public Point Way { get; set; }
    }
}

Если я использую Dapper, то я получаю свойство Way с координатами геометрии:

using (NpgsqlConnection conn = new NpgsqlConnection(_connectionString))
{
    conn.Open();
    conn.TypeMapper.UseNetTopologySuite();
    var result = conn.Query<OsmPoint>("SELECT * FROM planet_osm_point LIMIT 5000").ToList();
    return result;
}

Но если я использую Dapper.fastCRUD, то Путь всегда будет нулевым

using (NpgsqlConnection conn = new NpgsqlConnection(_connectionString))
{
    conn.Open();
    conn.TypeMapper.UseNetTopologySuite();
    var result = conn.Find<OsmPoint>(p=>p.Top(5000));
    return result;
}

Кто-нибудь знает, как заставить Dapper.fastCRUD работать с геометрическими данными?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Dapper.FastCRUD по умолчанию использует только упрощенные типы sql для построения запросов.Вы можете увидеть это в Dapper.FastCrud.Configuration.OrmConventions.cs:

public virtual IEnumerable<PropertyDescriptor> GetEntityProperties(Type entityType)
{
    return TypeDescriptor.GetProperties(entityType)
        .OfType<PropertyDescriptor>()
        .Where(propDesc => 
            !propDesc.Attributes.OfType<NotMappedAttribute>().Any()
            && !propDesc.IsReadOnly 
            && propDesc.Attributes.OfType<EditableAttribute>().All(editableAttr => editableAttr.AllowEdit)
            && this.IsSimpleSqlType(propDesc.PropertyType));
}

Я переопределяю метод IsSimpleSqlType (Type propertyType):

public class GeometryConvention: OrmConventions
{
    protected override bool IsSimpleSqlType(Type propertyType)
    {
        var res = base.IsSimpleSqlType(propertyType) || propertyType.BaseType != null && propertyType.BaseType.Name.StartsWith("geometry", StringComparison.OrdinalIgnoreCase);
        return res;
    }
}

Зарегистрировать пользовательское соглашение:

OrmConfiguration.Conventions = new GeometryConvention();

И используйте пользовательский GeometryTypeMapper, например, в ответе Long Ngô Thành.

0 голосов
/ 15 октября 2018

Сначала вы создаете TypeHandler для типа Geometry следующим образом:

public class GeometryTypeMapper : SqlMapper.TypeHandler<Geometry>
{
    public override void SetValue(IDbDataParameter parameter, Geometry value)
    {
        if (parameter is NpgsqlParameter npgsqlParameter)
        {
            npgsqlParameter.NpgsqlDbType = NpgsqlDbType.Geometry;
            npgsqlParameter.NpgsqlValue = value;
        }
        else
        {
            throw new ArgumentException();
        }
    }

    public override Geometry Parse(object value)
    {
        if (value is Geometry geometry)
        {
            return geometry;
        }

        throw new ArgumentException();
    }
}

добавить обработчик типа:

SqlMapper.AddTypeHandler(new GeometryTypeMapper());

установить свойство перед запросом по FastCURD:

OrmConfiguration.GetDefaultEntityMapping<OsmPoint>().SetProperty(p => p.way, prop => prop.SetDatabaseColumnName("way"));
...