简体   繁体   English

如何使用 C# 从 SQL 服务器检索点?

[英]How can I retrieve a Point from SQL Server with C#?

i'm using spacial data type on my sql server and I want to retrieve this data from my sql server to my Entity Class, it returns the error ".NET number values such as positive and negative infinity cannot be written as valid JSON." i'm using spacial data type on my sql server and I want to retrieve this data from my sql server to my Entity Class, it returns the error ".NET number values such as positive and negative infinity cannot be written as valid JSON." when i try to Get the value from my db.当我尝试从我的数据库中获取值时。

Coordinates is the value I want to return from my db.坐标是我想从我的数据库返回的值。 I'm using Geography data type from NetTopologySuite and i'm inserting a Point from my Entity Class.我正在使用来自 NetTopologySuite 的地理数据类型,并且正在从我的实体 Class 中插入一个点。

在此处输入图像描述

The class code that i'm using:我正在使用的 class 代码:

public class Address : EntityBase<int>
{
    public Address () {}

    public Address(string district, string street, int number, string complement, string zipCode, 
    string cityDescription, string stateDescription, Point coordinates, int countryId, byte stateId, int cityId)
    {
        District = district;
        Street = street;
        Number = number;
        Complement = complement;
        ZipCode = zipCode;
        CityDescription = cityDescription;
        StateDescription = stateDescription;
        Coordinates = coordinates;
        CountryId = countryId;
        StateId = stateId;
        CityId = cityId;
    }

    public string District { get; set; }
    public string Street { get; set; }
    public int Number { get; set; }
    public string Complement { get; set; }
    public string ZipCode { get; set; }
    public string CityDescription { get; set; }
    public string StateDescription { get; set; }
    public virtual Point Coordinates { get; set; }
    public int CountryId { get; set; }
    public byte StateId { get; set; }
    public int CityId { get; set; }
    public int? CustomerId { get; set; }
    public int? StoreId { get; set; }
    public int? ProfessionalId { get; set; }
}

And the sql server code for the table:以及表的 sql 服务器代码:

CREATE TABLE Address(
    Id INT PRIMARY KEY IDENTITY(1, 1),
    District VARCHAR(50) NOT NULL, -- Bairro
    Street VARCHAR(100) NOT NULL, -- Rua
    --Description VARCHAR(100) NOT NULL,
    Number INT,
    Complement VARCHAR(100),
    ZipCode VARCHAR(20) NOT NULL,
    CityDescription VARCHAR(100),
    StateDescription VARCHAR(100),
    Coordinates GEOGRAPHY,
    
    CountryId INT FOREIGN KEY REFERENCES Country(Id) NOT NULL,
    StateId TINYINT FOREIGN KEY REFERENCES State(Id),
    CityId INT FOREIGN KEY REFERENCES City(Id),
    CustomerId INT FOREIGN KEY REFERENCES Customer(Id),
    StoreId INT FOREIGN KEY REFERENCES Store(Id),
    ProfessionalId INT FOREIGN KEY REFERENCES Professional(Id),

    INDEX IndexAddressCountryId NONCLUSTERED (CountryId),
    INDEX IndexAddressStateId NONCLUSTERED (StateId),
    INDEX IndexAddressCityId NONCLUSTERED (CityId),
    INDEX IndexAddressCustomerId NONCLUSTERED (CustomerId),
    INDEX IndexAddressStoreId NONCLUSTERED (StoreId),
    INDEX IndexAddressProfessionalId NONCLUSTERED (ProfessionalId)
)

Is there any method to retrieve the Point value from this?有什么方法可以从中检索点值吗? Like a configuration on function OnModelCreating or something else?像 function OnModelCreating上的配置还是其他什么? Can I only retrieve the longitude and latitude from it?我只能从中检索经度和纬度吗?

I'm new to Spacial Data so I don't know much about it.我是空间数据的新手,所以我不太了解它。 Thanks in advance for helping me:)提前感谢您帮助我:)


Edit 1:编辑1:

Here's the exception error that i get:这是我得到的异常错误:

在此处输入图像描述

EntityBase:实体库:

namespace CodenApp.Framework.Core.Entities
{
    public abstract class EntityBase<T>
    {
        public T Id { get; set; }
    }
}

And the two functions that I use to handle Exceptions:还有我用来处理异常的两个函数:

public async Task InvokeAsync(HttpContext httpContext)
{
    try
    {
        await _next(httpContext);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, ex.ToString());                
        await HandleExceptionAsync(httpContext, ex);
    }
}


protected override Task HandleExceptionAsync(HttpContext context, Exception exception)
{
    if(context == null)
        throw new ArgumentNullException(nameof(context));
    if(exception == null)
        throw new ArgumentNullException(nameof(exception));

    context.Response.ContentType = "application/json";
    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
    return context.Response.WriteAsync(ApiCatch.Log(exception).ToString());
}

The code that I used to convert to Point:我用来转换为 Point 的代码:

public static Point ConvertToGeometry(string coordinatesAux)
{
    if(coordinatesAux == null)
        throw new NullReferenceException();

    NumberFormatInfo formatProvider = new NumberFormatInfo();
    formatProvider.NumberGroupSeparator = ".";
            
    var currentLocation = new Point(new Coordinate(
                                        Convert.ToDouble(coordinatesAux.Substring(0, coordinatesAux.IndexOf(",")), formatProvider), 
                                        Convert.ToDouble(coordinatesAux.Substring(coordinatesAux.IndexOf(",") + 1), formatProvider))) { SRID = 4326 };
            
    return currentLocation;                                                            
}

As Panagiotis Kanavos said in the comments, to solve this situation I needed to add the NuGet package NetTopologySuite.IO.GeoJSON4STJ and change the file Startup.cs to recieve the changes given by the package. As Panagiotis Kanavos said in the comments, to solve this situation I needed to add the NuGet package NetTopologySuite.IO.GeoJSON4STJ and change the file Startup.cs to recieve the changes given by the package.

Changes in Startup.cs inside ConfigureServices function: ConfigureServices function 内的 Startup.cs 更改:

services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Point))); 
    options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Coordinate))); 
    options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(LineString))); 
    options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(MultiLineString))); 
});

services.AddControllers().AddJsonOptions(options =>
{
    var geoJsonConverterFactory = new GeoJsonConverterFactory();
    options.JsonSerializerOptions.Converters.Add(geoJsonConverterFactory);
});

services.AddSingleton(NtsGeometryServices.Instance);

And added the IOptions to my Controller:并将 IOptions 添加到我的 Controller 中:

private readonly IOptions<JsonOptions> _jsonOptions;
public StoreController(IAsyncRepository<Store, int> repository, StoreHandler handler, IOptions<JsonOptions> jsonOptions) : base(repository)
{
    _handler = handler;
    _orders = new Expression<Func<Store, object>>[] { x => x.Id };
    _jsonOptions = jsonOptions;
}

So taught in this wiki .所以在这个wiki中教授。

You could simply JSON ignore the porperty causing issues and create properties that display values in an acceptable format.您可以简单地 JSON 忽略导致问题的属性并创建以可接受的格式显示值的属性。 Here is how I went about this:这是我的做法:

public class LocationResult
{
    public Guid id { get; set; }
    [JsonIgnore]
    public GeoCoordinate geo { get; set; }
    public double latitude
    {
        get
        {
            return geo.Latitude;
        }
    }
    public double longitude
    {
        get
        {
            return geo.Longitude;
        }
    }
}

PLEASE NOTE: I know this is for a different object type than listed above, however the approach will still work with the properties adjusted.请注意:我知道这是针对与上面列出的不同的 object 类型,但是该方法仍然适用于调整后的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM