タイププラグインについて
以下のタイププラグインをサポートしています。
NodaTime
PostgrSQLの日付/時刻データ型をNodatimeとして扱うためのプラグイン。
Json.NET
PostgreSQLのJSONデータ型(json型およびjsonb型)を読み書きするときにNpgsqlがNewtonSoft JsonNETライブラリを使用できるようします。これにより、JSONデータ型のまま扱うことができます。
NetTopologySuite
PostGISのデータ型をNetTopologySuiteとして扱うためのプラグイン。NpgsqlがPostGIS空間タイプをNetTopologySuite(.NETの主要な空間ライブラリ)に直接マッピングできます。
GeoJSON
PostGISのデータ型をGeoJSON.NETとして扱うためのプラグイン。NpgsqlがGeoJSONライブラリを介してPostGIS空間タイプをGeoJSONとして読み書きできます。
アプリケーションでプラグインをセットアップするには、プラグインに依存関係を追加します(プロジェクトにインストールされたときに自動的に行われます)。以下のコードは、Npgsql.NodaTimeプラグインの例です。
using Npgsql; // Place this at the beginning of your program to use NodaTime everywhere (recommended) NpgsqlConnection.GlobalTypeMapper.UseNodaTime(); // Or to temporarily use NodaTime on a single connection only: conn.TypeMapper.UseNodaTime();
プラグインがセットアップされると、以下のようにNodaTimeオブジェクトを読み書きすることができます。
// Write NodaTime Instant to PostgreSQL "timestamp without time zone" using (var cmd = new NpgsqlCommand(@"INSERT INTO mytable (my_timestamp) VALUES (@p)", conn)) { cmd.Parameters.Add(new NpgsqlParameter("p", Instant.FromUtc(2011, 1, 1, 10, 30))); cmd.ExecuteNonQuery(); } // Read timestamp back from the database as an Instant using (var cmd = new NpgsqlCommand(@"SELECT my_timestamp FROM mytable", conn)) using (var reader = cmd.ExecuteReader()) { reader.Read(); var instant = reader.GetFieldValue<Instant>(0); }
タイププラグインの修正を適用するためには、下記のいずれかを実施します。
タイププラグインのアンインストール (“4.5.2 .NET Data Provider タイププラグインのアンインストール”を参照) を実施後、タイププラグインをセットアップ (“4.2.2 .NET Data Provider タイププラグインのセットアップ”を参照) する。
ソリューションのpackagesディレクトリからタイププラグインのディレクトリを削除したのち、nuget restoreコマンドにより復元する。
タイププラグインを使用したアプリケーションを配布する際、配布物の中にタイププラグインが含まれます。そのため、タイププラグインに関する修正を適用したのち、アプリケーションを再度ビルドし、更新されたアプリケーションを再配布する必要があります。
各タイププラグインに関する注意事項
各タイププラグインに関する注意事項を説明します。
PostgreSQLのデータ型とNodatimeのデータ型のマッピングを説明します。
PostgreSQLの | 既定のNodaTime 型 | 追加されるNodaTime 型 | 備考 |
---|---|---|---|
timestamp with time zone | Instant | ZonedDateTime(注1), OffsetDateTime(注1) | データベース内のUTCタイムスタンプです。UTC ZonedDateTimeおよびOffsetDateTimeのみがサポートされます。 |
timestamp without time zone | LocalDateTime(注2) | 未知または暗黙のタイムゾーンのタイムスタンプです。 | |
date | LocalDate | タイムゾーンやオフセット情報を持たない単純な日付です。 | |
time without time zone | LocalTime | タイムゾーンやオフセット情報を持たない単純な時刻です。 | |
time with time zone | OffsetTime | 時刻とオフセットを格納する型です。一般的に使用は推奨されません。 | |
interval | Period | Duration | 秒未満の単位から年までの時間間隔です。[NodaTime Duration] は、日とそれより短い間隔でサポートされていますが、年や月ではサポートされていません (これらには絶対期間がないため) 。期間は、任意の間隔単位で使用できます。 |
tszrange | Interval | NpgsqlRange<Instant> など | 2つの時間インスタンス(開始と終了)間の時間間隔です。 |
strange | NpgsqlRange<LocalDateTime> | 未知または暗黙のタイムゾーンの2つのタイムスタンプ間の時間間隔です。 | |
daterange | DateInterval | NpgsqlRange<LocalDate> など | 2つの日付の間隔です。 |
注1) Npgsql.EnableLegacyTimestampBehaviorが有効な場合、ZonedDateTimeまたはOffsetDateTimeの書き込みまたは読み取りは自動的にUTCに変換されます。
注2) Npgsql.EnableLegacyTimestampBehaviorが有効な場合 、timestamp without time zoneはデフォルトでLocalDateTimeではなくInstantにマップされます。
JSONプラグインがセットアップされると、ユーザーは透過的にCLRオブジェクトをJSON値として読み書きでき、プラグインはそれらを自動的にシリアル化/逆シリアル化します。
以下にコード例を示します。
// Write arbitrary CLR types as JSON using (var cmd = new NpgsqlCommand(@"INSERT INTO mytable (my_json_column) VALUES (@p)", conn)) { cmd.Parameters.Add(new NpgsqlParameter("p", NpgsqlDbType.Jsonb) { Value = MyClrType }); cmd.ExecuteNonQuery(); } // Read arbitrary CLR types as JSON using (var cmd = new NpgsqlCommand(@"SELECT my_json_column FROM mytable", conn)) using (var reader = cmd.ExecuteReader()) { reader.Read(); var someValue = reader.GetFieldValue<MyClrType>(0); }
デフォルトでは、プラグインはGeometryServiceProvider.InstanceのDefaultCoordinateSequenceFactoryによって提供される縦座標のみを処理します。 GeometryServiceProviderが自動的に初期化されると、X座標とY座標が処理されます。動作を変更するには、次の例のようにhandleOrdinatesパラメーターを指定します。
conn.TypeMapper.UseNetTopologySuite(handleOrdinates: Ordinates.XYZ);
M座標を処理するには、GeometryServiceProvider.InstanceをDotSpatialAffineCoordinateSequenceFactory に設定されたcoordinateSequenceFactoryを使用して、新しいNtsGeometryServicesインスタンスに初期化する必要があります。
// Place this at the beginning of your program to use the specified settings everywhere (recommended) GeometryServiceProvider.Instance = new NtsGeometryServices( new DotSpatialAffineCoordinateSequenceFactory(Ordinates.XYM), new PrecisionModel(PrecisionModels.Floating), -1); // Or specify settings for Npgsql only conn.TypeMapper.UseNetTopologySuite( new DotSpatialAffineCoordinateSequenceFactory(Ordinates.XYM));
データベースからPostGIS値を読み込むと、Npgsqlは適切なNetTopologySuite型(Point、LineStringなど)を自動的に返します。 Npgsqlは、パラメーター内のNetTopologySuite型を自動的に認識し、対応するPostGIS型タイプをデータベースに自動的に送信します。以下のコードは、データベースとNetTopologySuite型のやりとりを示しています。
var point = new Point(new Coordinate(1d, 1d)); conn.ExecuteNonQuery("CREATE TEMP TABLE data (geom GEOMETRY)"); using (var cmd = new NpgsqlCommand("INSERT INTO data (geom) VALUES (@p)", conn)) { cmd.Parameters.AddWithValue("@p", point); cmd.ExecuteNonQuery(); } using (var cmd = new NpgsqlCommand("SELECT geom FROM data", conn)) using (var reader = cmd.ExecuteReader()) { reader.Read(); Assert.That(reader[0], Is.EqualTo(point)); }
NpgsqlDbType.Geometryを設定して、パラメータの型を明示的に指定することもできます。
PostGISには、ジオメトリ(デカルト座標の場合)とジオグラフィ(測地座標または球面座標の場合)の2つのタイプがあります。 ジオメトリとジオグラフィの違いについては、PostGISドキュメントを参照してください。ジオグラフィは長距離の計算を行う場合にはるかに正確ですが、計算コストが高くなり、ジオメトリでサポートされる空間操作の小さなサブセットのみをサポートします。
Npgsqlは同じNetTopologySuiteタイプを使用してジオメトリとジオグラフィの両方を表現します。Pointタイプはデカルト空間またはジオグラフィ空間のいずれかのポイントを表します。 通常、PostgreSQLは必要に応じて型をキャストするため、この区別について考慮は不要です。ただし、Npgsqlはデフォルトでデカルトジオメトリを送信することに注意してください。NpgsqlDbType.Geographyを指定することにより、代わりにジオグラフィを送信するようにNpgsqlに指示するオプションがあります。
using (var cmd = new NpgsqlCommand("INSERT INTO data (geog) VALUES (@p)", conn)) { cmd.Parameters.AddWithValue("@p", NpgsqlDbType.Geography, point); cmd.ExecuteNonQuery(); }
デフォルトでジオグラフィを使用したい場合は、プラグインをセットアップするときにそれを指定することもできます。
NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite(geographyAsDefault: true);
GeoJSONプラグインの使用方法は、NetTopologuSuiteと同じです。
名前付きパラメータのプレフィックスは、「@」を設定してください。
引用符(“) で囲んでも大文字のオブジェクト名を使用することはできません。
クエリビルダーではなく、[SQLステートメントの入力]画面で、引用符(“) で囲んだ大文字のオブジェクト名を含むSQL文を入力して使用してください。
以下のSQL文をFilterに指定して正しいSQL文を生成できません。
PostgreSQLの固有演算子(<<、:: など)を使ったSQL文
「AS、FROM、IN、OVER」などのキーワードがある関数を使ったSQL文
例: extract(field from timestamp)、RANK( ) OVER
SQL規約に規定されている関数と関数名は同じであるが、引数の異なる関数を使ったSQL文
GetSchemaTableでメタデータを取得する前にExecuteReaderメソッドを実行する場合、ExecuteReaderメソッドの引数にCommandBehavior.KeyInfoを指定する必要があります。
例
NpgsqlDataReader ndr=cmd.ExecuteReader(CommandBehavior.KeyInfo); DataTable dt = dr.GetSchemaTable();
以下の更新不可能な問合せを含むSQL文に対し、更新系のSQL文が生成され、そのSQL文が実行できない場合があります。
導出表を含む問合せ
選択リストに同じ列名を含む問合せ
更新系SQL文は以下の場合に自動生成されます。
NpgsqlCommandBuilderで更新文を取得
NpgsqlDataAdapterでデータ更新を実行
分散トランザクションに関する注意事項
トランザクションスコープを利用するアプリケーションは、Microsoft Distributed Transaction Coordinator(MSDTC)と連携することで、分散トランザクションとして動作することができます。この場合、以下の注意が必要です。
データベースサーバに同時接続する各トランザクションに対して「PREPARE TRANSACTION」を発行できるようにするため、max_prepared_transactionsパラメータの値をmax_connectionパラメータの値より大きくしてください。
トランザクションスコープ内の各トランザクションが、別々のコネクションを使って同じ資源にアクセスすると、データベースサーバでは異なるアプリケーションから要求があるように見え、デッドロックが発生する可能性がありますので注意してください。あらかじめトランザクションスコープにタイムアウト値を設定しておけば、デッドロックを解除することができます。