Bagikan melalui


Data spasial

Data spasial mewakili lokasi fisik dan bentuk objek. Banyak database menyediakan dukungan untuk jenis data ini sehingga dapat diindeks dan dikueri bersama data lainnya. Skenario umum termasuk mengkueri objek dalam jarak tertentu dari lokasi, atau memilih objek yang batasnya berisi lokasi tertentu. EF Core mendukung pemetaan ke jenis data spasial menggunakan pustaka spasial NetTopologySuite.

Menginstal

Untuk menggunakan data spasial dengan EF Core, Anda perlu menginstal paket NuGet pendukung yang sesuai. Paket mana yang perlu Anda instal tergantung pada penyedia yang Anda gunakan.

Penyedia Inti EF Paket NuGet Spasial
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) adalah pustaka spasial untuk .NET. EF Core memungkinkan pemetaan ke jenis data spasial dalam database dengan menggunakan jenis NTS dalam model Anda.

Untuk mengaktifkan pemetaan ke jenis spasial melalui NTS, panggil metode UseNetTopologySuite pada penyusun opsi DbContext penyedia. Misalnya, dengan SQL Server Anda akan menyebutnya seperti ini.

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

Ada beberapa jenis data spasial. Jenis mana yang Anda gunakan tergantung pada jenis bentuk yang ingin Anda izinkan. Berikut adalah hierarki jenis NTS yang dapat Anda gunakan untuk properti dalam model Anda. Mereka terletak di NetTopologySuite.Geometries dalam namespace layanan.

  • Geometri
    • Titik
    • LineString
    • Poligon
    • GeometryCollection
      • MultiPoint
      • MultiLineString
      • MultiPolygon

Peringatan

CircularString, CompoundCurve, dan CurePolygon tidak didukung oleh NTS.

Menggunakan jenis Geometri dasar memungkinkan semua jenis bentuk ditentukan oleh properti .

Garis Bujur dan Lintang

Koordinat dalam NTS dalam hal nilai X dan Y. Untuk mewakili garis bujur dan lintang, gunakan X untuk garis bujur dan Y untuk garis lintang. Perhatikan bahwa ini mundur dari latitude, longitude format di mana Anda biasanya melihat nilai-nilai ini.

Mengkueri Data

Kelas entitas berikut dapat digunakan untuk memetakan ke tabel dalam database sampel 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; }
}

Di LINQ, metode dan properti NTS yang tersedia sebagai fungsi database akan diterjemahkan ke SQL. Misalnya, metode Jarak dan Berisi diterjemahkan dalam kueri berikut. Lihat dokumentasi penyedia Anda untuk metode mana yang didukung.

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

Rekayasa terbalik

Paket NuGet spasial juga mengaktifkan model rekayasa terbalik dengan properti spasial, tetapi Anda perlu menginstal paket sebelum menjalankan Scaffold-DbContext atau dotnet ef dbcontext scaffold. Jika tidak, Anda akan menerima peringatan tentang tidak menemukan pemetaan jenis untuk kolom dan kolom akan dilewati.

SRID Diabaikan selama operasi klien

NTS mengabaikan nilai SRID selama operasi. Ini mengasumsikan sistem koordinat planar. Ini berarti bahwa jika Anda menentukan koordinat dalam hal garis bujur dan lintang, beberapa nilai yang dievaluasi klien seperti jarak, panjang, dan area akan berada dalam derajat, bukan meter. Untuk nilai yang lebih bermakna, Anda harus terlebih dahulu memproyeksikan koordinat ke sistem koordinat lain menggunakan pustaka seperti ProjNet (untuk GeoAPI).

Catatan

Gunakan paket ProjNet NuGet yang lebih baru, bukan paket lama yang disebut ProjNet4GeoAPI.

Jika operasi dievaluasi server oleh EF Core melalui SQL, unit hasil akan ditentukan oleh database.

Berikut adalah contoh penggunaan ProjNet untuk menghitung jarak antara dua kota.

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

Catatan

4326 mengacu pada WGS 84, standar yang digunakan dalam GPS dan sistem geografis lainnya.

Sumber Daya Tambahan:

Informasi khusus database

Pastikan untuk membaca dokumentasi penyedia Anda untuk informasi tambahan tentang bekerja dengan data spasial.

Sumber daya lainnya