以下のようなモデルがあります。
public class Mutant
{
public long Id { get; set; }
...
// Relations
public long OriginalCodeId { get; set; }
public virtual OriginalCode OriginalCode { get; set; }
public int DifficultyLevelId { get; set; }
public virtual DifficultyLevel DifficultyLevel { get; set; }
}
そして
public class OriginalCode
{
public long Id { get; set; }
...
// Relations
public virtual List<Mutant> Mutants { get; set; }
public virtual List<OriginalCodeInputParameter> OriginalCodeInputParameters { get; set; }
}
そしてOnModelCreating
のDBContext
私はこれらのような関係を作りました:
modelBuilder.Entity<Mutant>()
.HasOne(m => m.OriginalCode)
.WithMany(oc => oc.Mutants)
.HasForeignKey(m => m.OriginalCodeId)
.OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict);
modelBuilder.Entity<Mutant>()
.HasOne(m => m.DifficultyLevel)
.WithMany(dl => dl.Mutants)
.HasForeignKey(m => m.DifficultyLevelId)
.OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Restrict);
私がMutantsを要求すると、OriginalCodeはnullになります。
しかし、私がOriginalCode
を要求するとすぐに以下のようになります:
その場合、ミュータントのOriginalCode
フィールドはnullにはなりません。
その理由は何ですか?またどうすれば修正できますか?
理由は、EFコアのドキュメントの関連データの読み込みのセクションで説明されています。
最初の動作は、現在EF Coreが遅延読み込みをサポートしていないためです。通常、読み込み専用または読み込み専用の読み込みを行うまで、ナビゲーションプロパティにはnull
返されます。ただし、 Eager loadingセクションには次の内容が含まれています。
先端
Entity Framework Coreは、以前にコンテキストインスタンスにロードされた他のエンティティにナビゲーションプロパティを自動的に修正します。したがって、ナビゲーションプロパティのデータを明示的にインクルードしなくても、関連エンティティの一部またはすべてが以前にロードされていた場合でも、プロパティにデータが格納されることがあります。
2番目のケースでナビゲーションプロパティがnullではない理由が説明されています。
今、私は2つの行動のどちらを修正したいのか分からないので、両方に取り組もうとします。
最初の動作は、関連するデータをロードするために現在利用可能なメソッドの1つ、例えば熱心なロードを使用することによって "固定"することができます。
var mutants = db.Mutants.Include(m => m.OriginalCode).ToList();
2番目の動作は「設計通り」であり、制御できません。それを避けたい場合は、必要なデータを再試行するために単一のクエリを実行するためだけに新しいDbContext
インスタンスを使用してください。
アップデート: v2.1以降、EFコアはレイジーロードをサポートしています。ただし、デフォルトでは有効になっていないため、すべてのナビゲーションプロパティをvirtual
、 Microsoft.EntityFrameworkCore.Proxiesをインストールし、 UseLazyLoadingProxies
呼び出しで有効にするか、 プロキシなしでLazy-loadingを使用する必要があります。どちらもEFコアドキュメンテーション。