はじめに
SQLServerでGeography型のカラムを扱う方法です
必要なパッケージ
Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite 5.0.2
NetTopologySuite support for the Microsoft SQL Server database provider for Entity Framework Core.
テーブル構造
例として店舗の座標を保存するだけのテーブルとします
create table stores
(
id int identity constraint stores_pk primary key nonclustered,
location geography not null
)
DbContext関連
Store.cs
using System.ComponentModel.DataAnnotations.Schema;
using NetTopologySuite.Geometries;
namespace GeoTest
{
public class Store
{
[Column("id")]
public int Id { get; set; }
[Column("location")]
public Point Location { get; set; }
}
}
※この例ではLocationに座標が入る前提のため型をPointにしていますが、PointだけではなくPolygonなどが混在する可能性がある場合は型をIGeometryにします
Db.cs
using Microsoft.EntityFrameworkCore;
namespace GeoTest
{
public class Db : DbContext
{
public DbSet<Store> Stores { get; set; }
public Db(DbContextOptions options) : base(options)
{
}
}
}
Startup.csの変更
ConfigureServicesに下記を追加します
※接続文字列は適宜変更してください
services.AddDbContext<Db>(op => {
op.UseSqlServer([接続文字列], x => x.UseNetTopologySuite());
});
使い方
コントローラーにDbがインジェクションされます
using Microsoft.AspNetCore.Mvc;
using NetTopologySuite.Geometries;
namespace GeoTest.Controllers
{
public class HomeController : Controller
{
private Db _db;
public HomeController(Db db)
{
_db = db;
}
public IActionResult Index()
{
return View();
}
}
}
データ作成
_db.Stores.Add(new Store{ Location = new Point(139.768773, 35.680456){ SRID = 4326} });
SRIDを指定しないとエラーになります
この例では4326(世界測地系)を指定しています
空間検索
var stores = _db.Stores.Where(s => s.Location.Intersects(new Point(139.768773, 35.680456) {SRID = 4326})).ToList();