LoginSignup
18
17

More than 3 years have passed since last update.

Entity Frameworkの関連のロード

Last updated at Posted at 2014-02-07

以下の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; // 普通に取れる
18
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
17