【问题标题】:How can I retrieve a Point from SQL Server with C#?如何使用 C# 从 SQL Server 检索点?
【发布时间】:2020-11-03 19:31:31
【问题描述】:

我在我的 sql server 上使用空间数据类型,我想从我的 sql server 检索这些数据到我的实体类,它返回错误 ".NET 数值,如正无穷和负无穷大写为有效的 JSON。” 当我尝试从我的数据库中获取值时。

坐标是我想从我的数据库返回的值。我正在使用来自 NetTopologySuite 的 Geography 数据类型,并且我正在从我的实体类中插入一个点。

我正在使用的课程代码:

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; }
}

以及表的sql server代码:

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)
)

有什么方法可以从中检索 Point 值吗?像功能 OnModelCreating 上的配置或其他什么?我只能从中检索经度和纬度吗?

我是空间数据的新手,所以我不太了解它。提前感谢您帮助我:)


编辑 1:

这是我得到的异常错误:

实体库:

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

还有我用来处理异常的两个函数:

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());
}

我用来转换为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;                                                            
}

【问题讨论】:

  • 该错误与 EF Core 或 Spatial 数据无关。 实际异常文本是什么?您可以使用Exception.ToString() 或单击异常弹出窗口上的Copy Details 轻松获取此信息。全文包含堆栈跟踪,显示哪个方法调用链导致了该异常。贴出引发此异常的实际代码
  • 空间数据与 JSON 无关。它于 2008 年添加到 SQL Server,比添加 JSON 支持早了 8 年。无论引发此异常,都与空间数据无关。顺便说一句,EntityBase 是什么?它是否有任何代码可以从/转换为 JSON?
  • @PanagiotisKanavos 这就是我要问的原因,因为我可以轻松发布该值,但是当我尝试检索它时,我得到了那个错误,所以我不知道是什么原因造成的。我正在使用 swagger 来测试我的 API
  • 您需要为此类型创建一个自定义的 JsonConverter 并将其注册到 ASP.NET Core。 ASP.NET Core 调用 System.Text.Json 将数据转换为 JSON。 NetTopologySuite 或相关软件包很可能已经包含这样的转换器

标签: c# sql-server entity-framework ef-core-3.1


【解决方案1】:

您可以简单地 JSON 忽略导致问题的属性并创建以可接受的格式显示值的属性。 这是我的做法:

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;
        }
    }
}

请注意:我知道这是针对与上面列出的对象类型不同的对象类型,但是该方法仍然适用于调整后的属性。

【讨论】:

    【解决方案2】:

    正如Panagiotis Kanavos在cmets中所说,为了解决这种情况我需要添加NuGet包NetTopologySuite.IO.GeoJSON4STJ并更改文件Startup.cs以接收包给出的更改。

    ConfigureServices 函数内 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);
    

    并将 IOptions 添加到我的控制器中:

    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;
    }
    

    所以在这个wiki.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      • 2021-01-25
      • 1970-01-01
      • 1970-01-01
      • 2013-03-04
      相关资源
      最近更新 更多