Sdílet prostřednictvím


Prostorová data

Prostorová data představují fyzické umístění a tvar objektů. Mnoho databází poskytuje podporu pro tento typ dat, aby je bylo možné indexovat a dotazovat společně s dalšími daty. Mezi běžné scénáře patří dotazování na objekty v dané vzdálenosti od umístění nebo výběr objektu, jehož ohraničení obsahuje dané umístění. EF Core podporuje mapování na prostorové datové typy pomocí prostorové knihovny NetTopologySuite.

Instalování

Pokud chcete použít prostorová data s EF Core, musíte nainstalovat odpovídající podpůrný balíček NuGet. Který balíček potřebujete nainstalovat, závisí na poskytovateli, kterého používáte.

Zprostředkovatel EF Core Balíček Spatial NuGet
Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite
Microsoft.EntityFrameworkCore.Sqlite Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite
Microsoft.EntityFrameworkCore.InMemory NetTopologySuite
Npgsql.EntityFrameworkCore.PostgreSQL Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite
Pomelo.EntityFrameworkCore.MySql Pomelo.EntityFrameworkCore.MySql.NetTopologySuite
Devart.Data.MySql.EFCore Devart.Data.MySql.EFCore.NetTopologySuite
Devart.Data.Oracle.EFCore Devart.Data.Oracle.EFCore.NetTopologySuite
Devart.Data.PostgreSql.EFCore Devart.Data.PostgreSql.EFCore.NetTopologySuite
Devart.Data.SQLite.EFCore Devart.Data.SQLite.EFCore.NetTopologySuite
Teradata.EntityFrameworkCore Teradata.EntityFrameworkCore.NetTopologySuite
FileBaseContext NetTopologySuite

NetTopologySuite

NetTopologySuite (NTS) je prostorová knihovna pro .NET. EF Core umožňuje mapování na prostorové datové typy v databázi pomocí typů NTS ve vašem modelu.

Chcete-li povolit mapování na prostorové typy přes NTS, zavolejte metodu UseNetTopologySuite v tvůrci možností DbContext zprostředkovatele. Například s SQL Serverem byste to nazvali takto.

options.UseSqlServer(
    @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=WideWorldImporters;ConnectRetryCount=0",
    x => x.UseNetTopologySuite());

Existuje několik prostorových datových typů. Jaký typ použijete, závisí na typech obrazců, které chcete povolit. Tady je hierarchie typů NTS, které můžete použít pro vlastnosti v modelu. Nachází se v NetTopologySuite.Geometries jmenném prostoru.

  • Geometrie
    • Bod
    • LineString
    • Mnohoúhelník
    • Sbírka Geometrií
      • MultiPoint
      • MultiLineString
      • MultiPolygon

Výstraha

NTS nepodporuje CircularString, CompoundCurve a CurvePolygon.

Použití základního typu Geometrie umožňuje, aby vlastnost určila libovolný typ obrazce.

Zeměpisná délka a zeměpisná šířka

Souřadnice v NTS jsou z hlediska hodnot X a Y. Pokud chcete znázorňovat zeměpisnou délku a zeměpisnou šířku, použijte pro zeměpisnou šířku X a Y. Všimněte si, že se jedná o opačný formát, než je latitude, longitude, ve kterém se tyto hodnoty obvykle zobrazují.

Dotazování dat

Následující třídy entit lze použít k mapování na tabulky v ukázkové databázi Wide World Importers.

[Table("Cities", Schema = "Application")]
public class City
{
    public int CityID { get; set; }

    public string CityName { get; set; }

    public Point Location { get; set; }
}
[Table("Countries", Schema = "Application")]
public class Country
{
    public int CountryID { get; set; }

    public string CountryName { get; set; }

    // Database includes both Polygon and MultiPolygon values
    public Geometry Border { get; set; }
}

V LINQ budou metody a vlastnosti NTS dostupné jako databázové funkce přeloženy do SQL. Například metody Vzdálenost a Obsahuje jsou přeloženy v následujících dotazech. Informace o podporovaných metodách najdete v dokumentaci poskytovatele.

// Find the nearest city
var nearestCity = await db.Cities
    .OrderBy(c => c.Location.Distance(currentLocation))
    .FirstOrDefaultAsync();
// Find the containing country
var currentCountry = await db.Countries
    .FirstOrDefaultAsync(c => c.Border.Contains(currentLocation));

Zpětná analýza

Balíčky Spatial NuGet také umožňují modely zpětného inženýrství s prostorovými vlastnostmi, ale musíte nainstalovat balíček před spuštěním nebo . Pokud to neuděláte, zobrazí se upozornění, že nenajdete mapování typů pro sloupce a sloupce se přeskočí.

Identifikátor SRID se během klientských operací ignoroval.

Protokol NTS ignoruje hodnoty SRID během operací. Předpokládá plánový souřadnicový systém. To znamená, že pokud zadáte souřadnice z hlediska délky a šířky, některé hodnoty vyhodnocené klientem, jako je vzdálenost, délka a oblast, budou ve stupních, ne v metrech. Pro smysluplnější hodnoty je nejprve potřeba promítnout souřadnice do jiného souřadnicového systému pomocí knihovny, jako je ProjNet (pro GeoAPI).

Poznámka:

Použijte novější balíček NuGet ProjNet, nikoli starší balíček s názvem ProjNet4GeoAPI.

Pokud se operace vyhodnocuje prostřednictvím SQL pomocí EF Core, bude jednotka výsledku určena databází.

Tady je příklad použití sítě ProjNet k výpočtu vzdálenosti mezi dvěma městy.

public static class GeometryExtensions
{
    private static readonly CoordinateSystemServices _coordinateSystemServices
        = new CoordinateSystemServices(
            new Dictionary<int, string>
            {
                // Coordinate systems:

                [4326] = GeographicCoordinateSystem.WGS84.WKT,

                // This coordinate system covers the area of our data.
                // Different data requires a different coordinate system.
                [2855] =
                    @"
                        PROJCS[""NAD83(HARN) / Washington North"",
                            GEOGCS[""NAD83(HARN)"",
                                DATUM[""NAD83_High_Accuracy_Regional_Network"",
                                    SPHEROID[""GRS 1980"",6378137,298.257222101,
                                        AUTHORITY[""EPSG"",""7019""]],
                                    AUTHORITY[""EPSG"",""6152""]],
                                PRIMEM[""Greenwich"",0,
                                    AUTHORITY[""EPSG"",""8901""]],
                                UNIT[""degree"",0.01745329251994328,
                                    AUTHORITY[""EPSG"",""9122""]],
                                AUTHORITY[""EPSG"",""4152""]],
                            PROJECTION[""Lambert_Conformal_Conic_2SP""],
                            PARAMETER[""standard_parallel_1"",48.73333333333333],
                            PARAMETER[""standard_parallel_2"",47.5],
                            PARAMETER[""latitude_of_origin"",47],
                            PARAMETER[""central_meridian"",-120.8333333333333],
                            PARAMETER[""false_easting"",500000],
                            PARAMETER[""false_northing"",0],
                            UNIT[""metre"",1,
                                AUTHORITY[""EPSG"",""9001""]],
                            AUTHORITY[""EPSG"",""2855""]]
                    "
            });

    public static Geometry ProjectTo(this Geometry geometry, int srid)
    {
        var transformation = _coordinateSystemServices.CreateTransformation(geometry.SRID, srid);

        var result = geometry.Copy();
        result.Apply(new MathTransformFilter(transformation.MathTransform));

        return result;
    }

    private class MathTransformFilter : ICoordinateSequenceFilter
    {
        private readonly MathTransform _transform;

        public MathTransformFilter(MathTransform transform)
            => _transform = transform;

        public bool Done => false;
        public bool GeometryChanged => true;

        public void Filter(CoordinateSequence seq, int i)
        {
            var x = seq.GetX(i);
            var y = seq.GetY(i);
            var z = seq.GetZ(i);
            _transform.Transform(ref x, ref y, ref z);
            seq.SetX(i, x);
            seq.SetY(i, y);
            seq.SetZ(i, z);
        }
    }
}
var seattle = new Point(-122.333056, 47.609722) { SRID = 4326 };
var redmond = new Point(-122.123889, 47.669444) { SRID = 4326 };

// In order to get the distance in meters, we need to project to an appropriate
// coordinate system. In this case, we're using SRID 2855 since it covers the
// geographic area of our data
var distanceInDegrees = seattle.Distance(redmond);
var distanceInMeters = seattle.ProjectTo(2855).Distance(redmond.ProjectTo(2855));

Poznámka:

4326 odkazuje na WGS 84, standard používaný v GPS a dalších geografických systémech.

Dodatečné zdroje

Informace specifické pro databázi

Další informace o práci s prostorovými daty najdete v dokumentaci vašeho poskytovatele.

Další zdroje informací