简体   繁体   中英

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." 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.

在此处输入图像描述

The class code that i'm using:

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:

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? 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:

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:

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.

Changes in Startup.cs inside ConfigureServices function:

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:

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 .

You could simply JSON ignore the porperty causing issues and create properties that display values in an acceptable format. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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