空間データとNetTopologySuite
Oracleデータベースに、物理的な場所とオブジェクトの形状を表す空間データを格納できます。ODP.NETにより、Oracle空間データをネイティブに操作できます。
EF Coreでは、NetTopologySuite (NTS)空間ライブラリを使用して空間データ型にマップします。Oracle EF Core 10以降、OracleデータベースのSDO_GEOMETRY空間データ型は、Oracle EF Core NTSライブラリを使用してアクセスおよびマップできます。
このライブラリを使用すると、Oracle空間列を.NET形状タイプ(点やポリゴンなど)にマップできます。OracleデータベースのLINQ文に、空間ロジック(距離や交差など)を含めることができます。EF Coreアプリケーションでは、Oracleデータベースの空間データの問合せ、挿入、更新および削除に標準の方法を使用できるようになりました。
設定
このOracle空間ライブラリは、NuGetギャラリにあるOracle.EntityFrameworkCore.NetTopologySuiteパッケージで入手できます。これは現在プレビュー中です。NuGetパッケージ・マネージャでは、Oracle EF Core空間型のサポートに必要な他のNTSパッケージが自動的に取得されます。
Oracle空間データをEF Coreで使用するアプリケーションを設定するには、次のステップに従います:
-
Oracle.EntityFrameworkCore.NetTopologySuiteパッケージを.NETプロジェクトに追加します。 -
DbContextを使用してそのライブラリを有効にします。拡張メソッドUseNetTopologySuite()により、空間プロバイダ設定を構成します(許可できる幾何学的計算許容誤差を制御する、空間許容レベルなど)。たとえば:services.AddDbContext<MyContext>(options => options.UseOracle("<CONNECTION STRING>", o => o.UseNetTopologySuite(tolerance: 0.01))); -
エンティティ・モデルにおいて、空間クラスを定義します。たとえば:
public class MySpatialEntity { public int Id { get; set; } // NetTopologySuite.Geometries.Point public Point Location { get; set; } } -
次のような、空間データのLINQを記述します
Point myPoint = new Point(10, 20); var nearby = context.MySpatialEntities .Where(e => e.Location.IsWithinDistance(myPoint, 1000)) .ToList();
機能
Oracle EF Coreでは、次の機能がサポートされています:
-
Oracleの
SDO_GEOMETRY列データを次のようなNTS .NETデータ型に自動的にマップする-
Point -
LineString -
Polygon -
MultiPoint -
MultiLineString -
MultiPolygon -
GeometryCollection
-
-
NTS .NET型に対してDML操作を実行する。
-
LINQの空間操作をOracle SQL空間ファンクションに変換する。
-
EF Coreの移行と、Oracle空間列を使用したデータベース・スキャフォールディング
-
UseNetTopologySuite()拡張メソッドでの許容範囲構成。-
許容範囲が指定されていない場合は、
0.005がデフォルト値として設定されます。
-
ノート:
Oracle Spatialでは、NTSにおける使用できない機能や制限付き機能のスーパーセットがサポートされています(曲線形状など)。EF Core空間サポートはNTS機能に限定されています。
Oracle NetTopologySuiteのメンバー
表5-6 NetTopologySuiteメソッドとOracle Spatialファンクションのマッピング
| NetTopologySuiteのメソッド | Oracle Spatialのファンクション |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
表5-7 NetTopologySuiteプロパティとOracle Spatialファンクションのマッピング
| NetTopologySuiteのプロパティ | Oracle Spatialのファンクション |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
制限事項と回避策
-
M値(メジャー座標): NTSを使用するOracle EF Coreでは、M値(メジャー)座標はサポートされていません。M座標やZM座標があるジオメトリでは、シリアライズの間にM値が削除されます。それは、生成された
SDO_GEOMETRYには含まれていません。Oracle Spatialからジオメトリを読み取るときに、M値は、対応するNTSジオメトリ・オブジェクトに実体化されません。回避策:
Mを認識した操作やLRS (線形参照システム)の操作の場合は、直接Oracle SQLまたはストアド・プロシージャを使用します:
例1: M値ジオメトリの読取り
次のM値があるジオメトリを含む、Oracle Database内のSDO_GEOMETRYオブジェクト:SDO_GEOMETRY( 3303, -- LineString with Z and M NULL, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10,20,5,100, 30,40,10,200) )Oracle Database内の
SDO_GEOMETRYオブジェクトを読み取るOracle EF Coreコードとその出力:// C# var segment = context.RoadSegments.First(); var coords = segment.Geometry.Coordinates; // output: Coordinate[0] = (10, 20, 5) Coordinate[1] = (30, 40, 10)M値(100、200)は削除されます。それらは、結果となるオブジェクトには出現しません。
例2: M値ジオメトリの書込み
M値でジオメトリを更新するOracle EF Coreコード:// C# // EF Model public class RoadSegment { public int Id { get; set; } public LineString Geometry { get; set; } } // SaveChanges Code: var segment = new RoadSegment { Geometry = new LineString(new[] { new CoordinateZM(10, 20, 5, 100), new CoordinateZM(30, 40, 10, 200) }) }; context.RoadSegments.Add(segment); context.SaveChanges();Oracle EF Coreコードを実行してジオメトリをM値で更新すると、Oracle Database内に次のSDO_GEOMETRYオブジェクトが生成されます:SDO_GEOMETRY( 2003, -- 2D LineString type (M is ignored) NULL, NULL, SDO_ELEM_INFO_ARRAY(1,2,1), SDO_ORDINATE_ARRAY(10,20,5, 30,40,10) ) -
Relate()メソッド: NTSのRelate()メソッドでは、Dimensionally Extended Nine-Intersection Model (DE-9IM)マトリックスを使用してジオメトリ間の空間関係が確認されます。Oracle Spatialでは、他の空間ライブラリで使用されているDE-9IMパターンではなく、位相関係マスクと呼ばれる別の手法が使用されます。Entity Framework CoreのLINQ問合せでDE-9IMパターンを使用してRelate()メソッドを使用した場合(標準のNTS使用方法)、これらのパターンはOracle SQLに正しく変換されません。DE-9IMパターンを使用した問合せは失敗するか、正しくない結果を返す可能性があります。回避策
DE-9IMマトリックスのかわりに、
Relate()メソッドに対する2番目のパラメータとしてOracle Spatialの関係マスク文字列を指定します。Oracle EF CoreのNTSライブラリでは、SQL変換の間に、SDO_RELATEマスク・パラメータに空間関係マスクとしてこの文字列が挿入されます。例
.Relate()とOracleマスクを使用したLINQ問合せ。次の問合せでは、Relate()メソッドを使用して、各行のジオメトリとターゲット・ジオメトリの間の空間関係を確認しており、DE-9IMパターンではなくOracle空間関係マスクTOUCHを指定しています。// C# var targetGeometry = factory.CreatePolygon(new[] { new Coordinate(0, 0), new Coordinate(10, 0), new Coordinate(10, 10), new Coordinate(0, 10), new Coordinate(0, 0) }); var result = context.GeometryEntities .Where(e => e.Geometry.Relate(targetGeometry, "TOUCH")) .Select(e => new { e.Id, e.Geometry }) .ToList();Oracle EF Coreでは、このLINQ式(.Relate()とOracleマスクを使用したLINQ問合せ)は次のOracle SQLに変換されます:SELECT e."Id", e."Geometry" FROM "GeometryEntities" e WHERE SDO_RELATE(e."Geometry", :targetGeometry, 'mask=TOUCH') = 'TRUE'Oracleでは、論理OR演算子(+)を使用して複数の関係マスクを組み合せることができます。