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.

Instalace

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.

Poskytovatel 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

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ázejí se v NetTopologySuite.Geometries oboru názvů.

  • Geometrie
    • Bod
    • Linestring
    • Mnohoúhelník
    • Geometrycollection
      • Multipoint
      • Multilinestring
      • Multipolygon

Upozorňující

NTS nepodporuje Kruhový řetězec, CompoundCurve a CurePolygon.

Použití základního typu geometrie umožňuje, aby byl vlastnost určen 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 zpětný formát latitude, longitude , ve kterém se tyto hodnoty obvykle zobrazují.

Dotazování na data

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 = db.Cities
    .OrderBy(c => c.Location.Distance(currentLocation))
    .FirstOrDefault();
// Find the containing country
var currentCountry = db.Countries
    .FirstOrDefault(c => c.Border.Contains(currentLocation));

Zpětná analýza

Balíčky Spatial NuGet také umožňují modely zpětné analýzy s prostorovými vlastnostmi, ale před spuštěním Scaffold-DbContext nebo .dotnet ef dbcontext scaffold 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 pomocí EF Core prostřednictvím SQL, 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.

Další prostředky

Informace specifické pro databázi

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

Další prostředky