実践 Entity Framework ~ ナビゲーションプロパティ
前回は、コードファーストを利用した、外部キーの設定方法について紹介しました。
外部キーの設定の時に利用した、ナビゲーションプロパティとはなんなんでしょう?
次のふたつのクラス(テーブル)に的を絞って考えます。
LINQ to SQL
繰り返しになりますが、地方自治体を表す Municipality クラスと、都道府県を表す Prefecture クラスです。
public class Municipality { [Key] public string Code { get; set; } // 外部キー public string PrefectureCode { get; set; } // ナビゲーションプロパティ public Prefecture Prefecture { get; set; } } public class Prefecture { [Key] public string Code { get; set; } public string Name { get; set; } } // 不要部分は省略
そしてコンテキストクラスです。
public class AddressDataContext : System.Data.Entity.DbContext { public DbSet<Prefecture> Prefectures { get; set; } public DbSet<Municipality> Municipalities { get; set; } }
マイグレーション適用済みでテーブルは既に作成されている状態とします。
例えば、自治体コード 13101(東京都千代田区)を取得したい場合は、次のようになります。
using(var context = new AddressDataContext()) { var entity = context.Municipalities.Where(q => q.Code == "13101").FirstOrDefault(); }
わかる方には当然のコードかと思います。
LINQ?ラムダ式?という方...検索するか、まぁそうなるんだと、とりあえず思っておいてください。
LINQは奥が深いので、今後記事にする予定です。
Municipalities と Prefectures の間には、リレーションシップが設定されています。
では、自治体コード 13101 の 都道府県情報を取得したい場合、どうなるでしょうか?
ナビゲーションプロパティが無い状態だと...
using (var context = new AddressDataContext()) { var entity = context.Municipalities .Where(m => m.Code == "13101") .Join(context.Prefectures, m => m.PrefectureCode, p => p.Code, (m, p) => p) .FirstOrDefault(); }
これでなくても良いかもしれませんが、Join メソッドを利用し、ちょっとわかり辛くなっちゃいますね。
で、ナビゲーションプロパティを利用すると...
using (var context = new AddressDataContext()) { var entity = context.Municipalities .Where(m => m.Code == "13101") .Select(m => m.Prefecture).FirstOrDefault(); }
少しスッキリしました。
1から多を参照
ところで、当然逆もあるかと思います。
「東京都」に含まれている、自治体を取得したいという場合、通常ならば...
using (var context = new AddressDataContext()) { var list = context.Prefectures .Where(p => p.Name == "東京都") .Join(context.Municipalities, p => p.Code, m => m.PrefectureCode, (p, m) => m) .ToList(); }
これにも、当然ナビゲーションプロパティがあります。
今度は Prefecture クラスに、次を追加します。
public ICollection<Prefecture> Municipalities { get; set; }
1から多を参照するわけですから、型がコレクションになります。また参照側クラス型を指定する必要があります。
ICollection(T)インターフェースとしていますが、このインターフェースをもつ、IList(T) だったり、実クラスの List(T) であっても問題ありません。
そうすれば...
using (var context = new AddressDataContext()) { var list = context.Prefectures.Where(p => p.Name == "東京都") .SelectMany(p => p.Municipalities) .ToList(); }
これで、全く同じ動作になります。
ナビゲーションプロパティで外部キーを設定
このふたつのナビゲーションプロパティのうち、どちらかひとつが指定されている場合、外部キーが自動設定されます。
また、プロパティ名は実テーブルには影響を与えないので、何でも構いません。変更しても Add-Migration する必要もありません。
そんな感じで、非常にざっくりとではありますが、ナビゲーションプロパティの働きと使用方法を紹介しました。
外部キーの設定に関しては、この内容だけでは対応できない場合もあるでしょう。
そもそも外部キーなんか必要ない、リレーションだけ組めれば、的な要件もあるかと思います。
そんなときの対応は...次回以降で見ていきましょう。