Я использую базу данных сервера Sql. У меня есть пространственные данные (тип данных geometry). Мне нужно прочитать их в веб-проекте C#, используя dapper.
В моем проекте я импортировал пакет nuget Microsoft.Spatial, который поддерживает OData v4.
Я думаю, что таким образом мой проект должен быть независимым от SQL Server.
Первая проблема, которую я обнаружил, - это понять, какой тип данных я должен использовать для сопоставления типа данных Sql geometry. Я пытаюсь использовать Microsfot.Spatial.Geometry, это абстрактный класс. Но я не уверен.
Тогда это запрос, который я пишу, и сопоставление, которое я выполняю с помощью 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());