以下のEntityでFoo.Barsのロードの説明。
public class SampleContext: DbContext
{
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
}
public class Foo
{
public long Id { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
}
public class Bar
{
public long Id { get; set; }
public long FooId { get; set; }
[ForeignKey("FooId")]
public virtual Foo Foo { get; set; }
}
LazyLoading
LazyLoadingEnabledがtrue
はじめてのfoo.Barsアクセス時にLazyロードが走ります。
LazyLoadingEnabledはtrueがデフォルト。
var foo = default(Foo);
using (var context = new SampleContext())
{
foo = context.Foos.Where(f => f.Id == 1).Single();
var bars1 = foo.Bars; // ここでLazyロード
}
var bar2 = foo.Bars; // いったんロードされているのでちゃんと取れる
var foo = default(Foo);
using (var context = new SampleContext())
{
foo = context.Foos.Where(f => f.Id == 1).Single();
}
// contextは破棄されているのにここでLazyロードしようとしてObjectDisposedException
var bars = foo.Bars;
LazyLoadingEnabledがfalse
var foo = default(Foo);
using (var context = new SampleContext())
{
context.Configuration.LazyLoadingEnabled = fales;
foo = context.Foos.Where(f => f.Id == 1).Single();
var bars = foo.Bars; // Lazyロードされずにbarsはnull
}
var foo = default(Foo);
using (var context = new SampleContext())
{
context.Configuration.LazyLoadingEnabled = fales;
foo = context.Foos.Where(f => f.Id == 1).Single();
}
var bars = foo.Bars; // Lazyロードされずにbarsはnull
明示的にロード
明示的にロードしておけばcontext.Configuration.LazyLoadingEnabled
にかかわらずcontext内外でBarsを読めます。
Include()
Include()を使うとFooとBarをまとめてロードできます。
基本的には処理に必要な関連はInclude()で一気にロードしておくべきです。
Include()はcontext.Foos.Include(f => f.Bars).Include(f => f.AnotherAssoc)
のようにつなげて書けます。
var foo = default(Foo);
using (var context = new SampleContext())
{
// ここでロード
foo = context.Foos.Include(f => f.Bars).Where(f => f.Id == 1).Single();
var bars1 = foo.Bars; // 普通に取れる
}
var bars2 = foo.Bars; // 普通に取れる
Load()
Load()を使うとBarを個別にロードできます。
Fooのロード量が多く、かつ、Barsをロードする必要があるFooは少量なときは、
Include()よりLoad()またはLazyロードに任せるのがいいです。
var foo = default(Foo);
using (var context = new SampleContext())
{
foo = context.Foos.Where(f => f.Id == 1).Single();
context.Entry(foo).Collection(f => f.Bars).Load(); // ここでロード
var bars1 = foo.Bars; // 普通に取れる
}
var bars2 = foo.Bars; // 普通に取れる