空間資料
空間資料代表物件的實體位置和形狀。 許多資料庫都支援這種類型的資料,以便與其他資料一起編制索引和查詢。 常見案例包括查詢指定距離某個位置內的物件,或選取框線包含指定位置的物件。 EF Core 支援使用 NetTopologySuite 空間程式庫對應至空間資料類型。
正在安裝
若要搭配 EF Core 使用空間資料,您必須安裝適當的支援 NuGet 套件。 您需要安裝的套件取決於您所使用的提供者。
EF Core 提供者 | 空間 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) 是適用于 .NET 的空間程式庫。 EF Core 可讓您使用模型中的 NTS 類型,對應至資料庫中的空間資料類型。
若要透過 NTS 啟用空間類型的對應,請在提供者的 DbCoNtext 選項產生器上呼叫 UseNetTopologySuite 方法。 例如,使用 SQL Server 時,您會呼叫它,如下所示。
options.UseSqlServer(
@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=WideWorldImporters;ConnectRetryCount=0",
x => x.UseNetTopologySuite());
有數種空間資料類型。 您使用的類型取決於您想要允許的圖形類型。 以下是可用於模型中屬性之 NTS 類型的階層。 它們位於 命名空間內 NetTopologySuite.Geometries
。
- 幾何
- Point
- LineString
- Polygon
- GeometryCollection
- MultiPoint
- MultiLineString
- MultiPolygon
警告
NTS 不支援 CircularString、CompoundCurve 和 CurePolygon。
使用基底 Geometry 類型可讓 屬性指定任何類型的圖形。
經度和緯度
NTS 中的座標以 X 和 Y 值表示。 若要代表經度和緯度,請將 X 用於經度,並使用 Y 表示緯度。 請注意,這會 從 latitude, longitude
您通常看到這些值的格式回溯 。
查詢資料
下列實體類別可用來對應至 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; }
}
在 LINQ 中,作為資料庫函式可用的 NTS 方法和屬性將會轉譯為 SQL。 例如,Distance 和 Contains 方法會在下列查詢中轉譯。 請參閱提供者的檔,以瞭解支援哪些方法。
// 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));
反向工程
空間 NuGet 套件也啟用 具有空間屬性的反向工程 模型,但您需要在執行 或 dotnet ef dbcontext scaffold
之前 Scaffold-DbContext
先安裝套件。 如果您未這麼做,您將會收到有關未尋找資料行類型對應,且將會略過資料行的警告。
在用戶端作業期間忽略 SRID
NTS 會在作業期間忽略 SRID 值。 它會假設平面座標系統。 這表示,如果您在經度和緯度方面指定座標,某些用戶端評估的值,例如距離、長度和區域會以度為單位,而不是公尺。 如需更有意義的值,您必須先使用 ProjNet 等 程式庫將座標投影到另一個座標系統(適用于 GeoAPI)。
注意
使用較 新的 ProjNet NuGet 套件 , 而不是 稱為 ProjNet4GeoAPI 的較舊套件。
如果透過 SQL 由 EF Core 評估作業,結果的單位將由資料庫決定。
以下是使用 ProjNet 來計算兩個城市之間的距離的範例。
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));
注意
4326 是指 WGS 84,這是 GPS 和其他地理系統中使用的標準。
其他資源
資料庫特定資訊
請務必閱讀提供者的檔,以取得使用空間資料的其他資訊。
其他資源
- NetTopologySuite Docs
- .NET Data Community Standup 會話 ,著重于空間資料和 NetTopologySuite。