SQL Server 2014 は geometry 型をサポートしていますが、EF6 では標準で geometry/geography を直接マッピングできないため、少し工夫が必要です。
🔹SQL Server 側
|
1 2 3 4 |
CREATE TABLE t_bridge ( _fid INT PRIMARY KEY, _geom geometry NULL, ); |
🔹byte[] に変換してマッピングする(失敗例1)
最初に、byte[] に変換してマッピングしましたが…
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[Table("t_bridge")] public class BridgeEntity { /// <summary>FID</summary> [Key, Column("_fid", Order = 0), DatabaseGenerated(DatabaseGeneratedOption.None)] public int Fid { get; set; } /// <summary>橋梁ID</summary> [Column("_geom")] public byte[] Geometory { get; set; } } public int InsertData(bridge) { var newBridge = new Mitoyo.BridgeInspection.Models.Entity.BridgeEntity(); newBridge.Fid = fid++; var wkt = new StringBuilder(); wkt.AppendFormat("POINT({0} {1})", bridge.PositionY, bridge.PositionX); var wktReader = new WKTReader(); var geometry = wktReader.Read(wkt.ToString()); var wkbWriter = new WKBWriter(); byte[] wkb = wkbWriter.Write(geometry1); newBridge.Geometory = wkb; this.NewBridgeDao.InsertData(newBridge); } |
データ保存時に以下の例外が発生しました。
|
1 2 3 4 5 6 7 8 9 10 |
内部例外 1: UpdateException: An error occurred while updating the entries. See the inner exception for details. 内部例外 2: SqlException: ユーザー定義のルーチンまたは集計 "geometry" を実行中に .NET Framework エラーが発生しました: System.FormatException: 24210: 予期しないバージョン 0 の Geometry 型を受け取りました。指定できるのは 2 以下のバージョンのみです。 System.FormatException: 場所 Microsoft.SqlServer.Types.GeoData.Read(BinaryReader r, SerializationVersion maxVersion, String strUnexpectedVersion, Boolean isGeography) 場所 Microsoft.SqlServer.Types.SqlGeometry.Read(BinaryReader r) 場所 SqlGeometry::.DeserializeValidate(IntPtr , Int32 , CClrLobContext* ) |
🔹SqlGeometry に変換してマッピングする(失敗例2)
次に、SqlGeometry に変換してマッピングしましたが…
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using Microsoft.SqlServer.Types; [Table("t_bridge")] public class BridgeEntity { /// <summary>FID</summary> [Key, Column("_fid", Order = 0), DatabaseGenerated(DatabaseGeneratedOption.None)] public int Fid { get; set; } /// <summary>橋梁ID</summary> [Column("_geom")] public SqlGeometry Geometory { get; set; } } public int InsertData(bridge) { var newBridge = new Mitoyo.BridgeInspection.Models.Entity.BridgeEntity(); newBridge.Fid = fid++; var wkt = new StringBuilder(); wkt.AppendFormat("POINT({0} {1})", bridge.PositionY, bridge.PositionX); SqlGeometry sqlGeom = SqlGeometry.STGeomFromText(new SqlChars(wkt), 2446); newBridge.Geometory = sqlGeom; this.NewBridgeDao.InsertData(newBridge); } |
データ保存時に上記と同じ例外が発生しました。
🔹DbGeometry に変換してマッピングする(成功例)
次にに、DbGeometry に変換してマッピングすると無事に登録できました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[Table("t_bridge")] public class BridgeEntity { /// <summary>FID</summary> [Key, Column("_fid", Order = 0), DatabaseGenerated(DatabaseGeneratedOption.None)] public int Fid { get; set; } /// <summary>橋梁ID</summary> [Column("_geom")] public DbGeometry Geometory { get; set; } } public int InsertData(bridge) { var newBridge = new Mitoyo.BridgeInspection.Models.Entity.BridgeEntity(); newBridge.Fid = fid++; var wkt = new StringBuilder(); wkt.AppendFormat("POINT({0} {1})", bridge.PositionY, bridge.PositionX); newBridge.Geometory = DbGeometry.FromText(wkt.ToString(), 2446); this.NewBridgeDao.InsertData(newBridge); } |
🔹DbGeometryとSqlGeometryの違いは
👉DbGeometry と SqlGeometry は似ていますが、役割や使い方が違います。
| 特徴 | DbGeometry | SqlGeometry |
| 名前空間 | System.Data.Entity.Spatial | Microsoft.SqlServer.Types |
| 主な用途 | EF6 のエンティティで geometry/geography を扱う |
SQL Server の geometry 型を直接操作 |
| マッピング | EF6 のエンティティで直接使える | 直接は使えない(変換必要) |
| メソッド | 基本的な生成/座標取得のみ | SQL Server の空間関数が全部使える |
| ポータビリティ | 抽象的 (SQL Server 固有でない) | SQL Server 専用 |