将 'SqlServer.Types.SqlGeometry' 映射到 'Microsoft.Spatial' 类型,用于 SQL-Server-Independent geography code with dapper

Map 'SqlServer.Types.SqlGeometry' into 'Microsoft.Spatial' types for SQL-Server-Independent geography code with dapper

我正在使用 Sql 服务器数据库。我有一些空间数据(geometry 数据类型)。我需要使用 dapper.

C# 网络项目中阅读它们

在我的项目中,我导入了 Microsoft.Spatial 支持 OData v4 的 nuget 包。 我认为这样我的项目应该是 SQL-Server-Independent.

我发现的第一个问题是了解应该使用哪种数据类型来映射 Sql geometry 数据类型。我正在尝试使用抽象的 Microsfot.Spatial.Geometry class。但是我不确定。

那么这是我正在编写的查询以及我正在使用 dapper 进行的映射:

string sql = @"SELECT ..., departureAddress.GeometryLocation AS DepartureCoordinates, arrivalAddress.GeometryLocation AS ArrivalCoordinates ...";

var infoResultset = await this._connection.QueryAsync<MyInfoClass, ..., MyInfoClass>(
    sql,
    (request, ...) =>
    {
        /* Nothing about spatial types */

        return result;
    }
);

当我 运行 项目时,我得到这个错误:

Dapper: Error parsing column 3 (DepartureCoordinates=POINT (12.496365500000024 41.9027835) - Object). Unable to cast object of type 'Microsoft.SqlServer.Types.SqlGeometry' to type 'Microsoft.Spatial.Geometry'.

我也尝试过使用 Microsoft.Spatial.GeometryPoint 但我得到了同样的错误(只是消息中的目标类型发生了变化)。

谁能帮我解决映射问题? 谢谢

我已经通过更改查询和创建新类型处理程序解决了问题:

string sql = @"SELECT ..., departureAddress.GeometryLocation.STAsText() AS DepartureCoordinates, arrivalAddress.GeometryLocation.STAsText() AS ArrivalCoordinates ...";

这是我编写的类型处理程序:

public class GeometryPointTypeHandler : SqlMapper.TypeHandler<GeometryPoint>
{
    //      POINT(X Y)
    //      POINT(X Y Z M)
    public override GeometryPoint Parse(object value)
    {
        if (value == null)
            return null;

        if (!Regex.IsMatch(value.ToString(), @"^(POINT \()(.+)(\))"))
            throw new Exception("Value is not a Geometry Point");

        //Get values inside the brackets
        string geometryPoints = value.ToString().Split('(', ')')[1];

        //Split values by empty space
        string[] geometryValues = geometryPoints.Split(' ');

        double x = this.ConvertToDouble(geometryValues[0]);
        double y = this.ConvertToDouble(geometryValues[1]);

        double? z = null;
        if (geometryValues.Length >= 3)
            z = this.ConvertToDouble(geometryValues[2]);

        double? m = null;
        if (geometryValues.Length >= 4)
            m = this.ConvertToDouble(geometryValues[3]);

        return GeometryPoint.Create(x, y, z, m);
    }

    public override void SetValue(IDbDataParameter parameter, GeometryPoint value)
    {
        throw new NotImplementedException();
    }

    private double ConvertToDouble(string value)
    {
        return double.Parse(value, CultureInfo.InvariantCulture);
    }
}

我没有实施SetValue因为我不需要它

最后我将处理程序添加到 dapper:

Dapper.SqlMapper.AddTypeHandler(new GeometryPointTypeHandler());