空間數據代表對象的實體位置和形狀。 許多資料庫都支援這種類型的數據,以便與其他數據一起編製索引和查詢。 常見案例包括查詢指定距離某個位置內的物件,或選取框線包含指定位置的物件。 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 |
FileBaseContext | 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
。
- 幾何學
- 點
- LineString(線串)
- 多邊形
- GeometryCollection
- MultiPoint
- 多行字符串
- MultiPolygon
警告
NTS 不支援 CircularString、CompoundCurve 和 CurePolygon。
使用基底幾何類型可以讓屬性指定任何類型的圖形。
經度和緯度
NTS 中的座標以 X 和 Y 值表示。 若要代表經度和緯度,請將 X 用於經度,並使用 Y 表示緯度。 請注意,這與您通常看到這些值的格式是相反的。
查詢資料
下列實體類別可以映射到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 = 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));
反向工程
空間 NuGet 套件也啟用具有空間屬性的反向工程模型,但您需要在執行 或 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。