WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

ASP.NET Core で DateOnly 型を使用

by WebSurfer 19. July 2022 13:28

先の記事「PostgreSQL で Movie チュートリアル (CORE)」で書きましたように、Npgsql 6.0 の timestamp with time zone 型と .NET の DateTime 型の扱いの不整合のため例外がスローされるという問題があります。

その記事では臨時処置的に Npgsql を 6.0 より前の動作に戻すオプションを追加して解決しましたが、恒久処置的には .NET の DateTime 型を DateOnly 型に変えて、対応する PostgreSQL の型を date 型にするべきではないかと思いました。

というわけでそれを試してみましたので以下に顛末を書いておきます。ASP.NET Core はまだ DateOnly 型を十分にサポートしてないようで、すんなりとはいかなかったです。ASP.NET Core で DateOnly 型を使うのは時期尚早なのかも。

(1) DateTime 型を DateOnly 型に変更

Movie クラスの ReleaseDateプロパティの DateTime 型を DateOnly 型に変更します。

DateTime 型を DateOnly 型に変更

(2) Add-Migration の実行

ソリューションをリビルドしてから、Visual Studio のパッケージマネージャーコンソールで Add-Migration DateOnly コマンドを実行します。結果、以下の画像の通り DateOnly クラスが Migrations フォルダに自動生成されます。

Add-Migration の実行結果

Movie クラスの ReleaseDate プロパティの DateOnly 型に該当する PostgreSQL の型は date となっています。

なお、Add-Migration DateOnly の DateOnly という名前は任意に指定できます。指定した名前で xxxxx_DateOnly.cs (xxxxx は作成日時) という名前のファイルが作成され、それに DateOnly という名前のクラスが定義されます。

(3) Update-Database の実行

Visual Studio のパッケージマネージャーコンソールで Update-Database コマンドを実行します。

Update-Database の実行結果

上の画像の ReleaseData 列を見てください。Update-Database の実行前は timestamp with time zone 型であったものが date 型に変更されています。

(4) プロジェクトの実行

以上で完了のはずなのですが、プロジェクトを実行して Index 画面を表示すると ReleaseDate の表示が変でした。html ソースは以下のとおりで、DataOnly のプロパティが表示されます。

<div class="display-label">Year</div>
<div class="display-field">2022</div>
<div class="display-label">Month</div>
<div class="display-field">7</div>
<div class="display-label">Day</div>
<div class="display-field">10</div>
<div class="display-label">DayOfWeek</div>
<div class="display-field">Sunday</div>
<div class="display-label">DayOfYear</div>
<div class="display-field">191</div>
<div class="display-label">DayNumber</div>
<div class="display-field">738345</div>

Movie クラスの ReleaseDate プロパティに DisplayFormat 属性を付与してみましたが何も効果はなかったです。

さらに、Create, Edit 操作では、ブラウザからは期待通りに ReleaseDate=2022-07-18 という形で送信されるものの、アクションメソッドの引数には 0001/01/01 が渡される、すなわちモデルバインディングできてないという問題がありました。

ググって調べてみると、DateOnlyTimeOnly.AspNet という NuGet パッケージが見つかりました。Web API 用とのことですが、とりあえず試してみることにしました。

DateOnlyTimeOnly.AspNet

NuGet パッケージをインストールしたら、Program.cs で UseDateOnlyTimeOnlyStringConverters を AddControllers のオプションとして登録します。

DateOnlyTimeOnly.AspNet

結果、Index 画面の ReleaseDate は 2022/07/18 という形で表示されるようになりました。Create, Edit 操作でのモデルバインディングも正しく行われるようになりました。

もちろん、AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); は削除しても例外は出ず、Create, Edit とも成功します。

ホントはこのような追加のパッケージなしでも DateTime 型を使った場合と同様に動くべきだと思うのですが・・・

Tags: , , , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。その後ブログ2を追加し、ここはプログラミング関係、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  December 2022  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar