WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

中間テーブルへのナビゲーションプロパティ

by WebSurfer 2023年5月3日 15:32

多対多のリレーションシップを関連付ける中間テーブルへのナビゲーションプロパティ定義の問題で ASP.NET Core MVC での Create, Edit に失敗するのにハマって悩みました。またハマることがないよう備忘録として書いておきます。

エンティティ クラス

上の画像は Microsoft のドキュメント「チュートリアル: ASP.NET MVC Web アプリでの EF Core の概要」のもので Enrollment が中間テーブルです。チュートリアルは Student テーブルの CRUD 操作を行う ASP.NET Core MVC アプリを作成するもので、これをこの記事の例に使います。

Visual Studio 2022 のテンプレートを使ってターゲットフレームワーク .NET 6.0 以降でプロジェクトを作ると、デフォルトでプロジェクト全体で「Null 許容」オプションが有効にされます。

「Null 許容」オプションが有効にされていると、チュートリアルの Student クラスの定義では LastName, FirstMiddleName, Enrollments プロパティ に対しては "null 非許容のプロパティ 'xxxxx' には、コンストラクタの終了時に null 以外の値が入っていなければなりません" という警告が出ます。

その警告を回避するのに、以下のように = null!; を追加したのですが、ナビゲーションプロパティ Enrollments に対してそれはダメでした。ASP.NET Core MVC アプリによる CRUD 操作のうち Create, Edit に失敗します。

public class Student
{
    public int ID { get; set; }
    public string LastName { get; set; } = null!;
    public string FirstMidName { get; set; } = null!;
    public DateTime EnrollmentDate { get; set; }

    // これはダメ。ASP.NET Core MVC での Create, Edit に失敗する
    public ICollection<Enrollment> Enrollments { get; set; } = null!;
}

なぜ失敗するかと言うと、上の定義の場合 Enrollments が ModelStateDictionary に含まれるようになり、値が null になるので ValidationState が Invalid となってしまうからのようです。下の画像を見てください。結果、ModelSate.IsValid が false になって SaveChangesAsync メソッドがスキップされてしまいます。

デバッグ結果

チュートリアルの次のステップ「チュートリアル: CRUD 機能を実装する - ASP.NET MVC と EF Core」で、Edit アクションメソッドに TryUpdateModelAsync<T> メソッドを使う方法が紹介されていますが、それも失敗します。

解決策は、リバースエンジニアリングで既存の同等なデータベースから生成されるコードをまねて、Enrollments プロパティを以下のようにすることだと思います。

public ICollection<Enrollment> Enrollments { get; } = 
                                          new List<Enrollment>();

そうすれば、下の画像の通り ModelStateDictionary には Enrollments は含まれなくなります。Edit アクションメソッドに TryUpdateModelAsync<T> メソッドを使った場合も期待通りの結果となります。

デバッグ結果

Tags: , , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar