📝

.NET6のSqlClientでSQLServerの空間情報を扱う方法

2022/09/22に公開

必要なパッケージ

Microsoft.Data.SqlClient
NetTopologySuite.IO.SqlServerBytes

テーブル構造

例として店舗の座標を保存するだけのテーブルとします

create table stores
(
    id int identity constraint stores_pk primary key nonclustered,
    location geography not null
)

データを取得する場合

カラムからbyte[]を取得し、SqlServerBytesReaderで読み込めばOKです

using (var con= new SqlConnection(connectionString))
{
    con.Open();
    var geometryReader = new SqlServerBytesReader { IsGeography = true };
    using (var cmd = con.CreateCommand())
    {
        cmd.CommandText = "SELECT * FROM stores";
        using (var dr = cmd.ExecuteReader())
        {
            var geo = geometryReader.Read(dr.GetSqlBytes(1).Value);
        }
    }
}

BulkCopyで一括挿入する場合

多少工夫が必要ですが、あらかじめDataTableを作成しBulkCopyで一括挿入することができます
ポイントはgeography型のDataRowをbyte[]とすることと、Geometryの変数をSqlServerBytesWriterでbyte[]として書き出す点です

var data = new DataTable();
data.Columns.Add("id");
data.Columns.Add("location", typeof(byte[])); // カラムの型をbyte[]とする

var row = data.NewRow();
var geometry = new Point(-122.129797, 47.640049) { SRID = 4326 };
var geometryWriter = new SqlServerBytesWriter { IsGeography = true };
row["location"] = geometryWriter.Write(geometry);
data.Rows.Add(row);

using (var con= new SqlConnection(connectionString))
{
    con.Open();
    using (var bc = new SqlBulkCopy(con))
    {
        bc.DestinationTableName = "stores";
        bc.WriteToServer(data);
    }
}

Discussion