web-dev-qa-db-ja.com

Entity Framework-オンデマンドで関連エンティティの遅延読み込みを停止しますか?

Entity Frameworkをセットアップしましたが、ほとんどの場合、必要になります。私はそのような構造を持っています

public partial class Topic : Entity
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public DateTime CreateDate { get; set; }
    public virtual Post LastPost { get; set; }
    public virtual Category Category { get; set; }
    public virtual IList<Post> Posts { get; set; }
    public virtual IList<TopicTag> Tags { get; set; }
    public virtual MembershipUser User { get; set; }
    public virtual IList<TopicNotification> TopicNotifications { get; set; }
    public virtual IList<Favourite> Favourites { get; set; }
    public virtual Poll Poll { get; set; }
}

ご覧のとおり、リストである関連エンティティがいくつかあります。これらは標準としてマップされ、遅延ロードされるため、Topic.PostsまたはTopic.TopicNotificationsなどを呼び出すことができます...(以下のマッピング)

HasOptional(t => t.LastPost).WithOptionalDependent().Map(m => m.MapKey("Post_Id"));
HasOptional(t => t.Poll).WithOptionalDependent().Map(m => m.MapKey("Poll_Id"));            
HasRequired(t => t.Category).WithMany(t => t.Topics).Map(m => m.MapKey("Category_Id"));
HasRequired(t => t.User).WithMany(t => t.Topics).Map(m => m.MapKey("MembershipUser_Id"));
HasMany(x => x.Posts).WithRequired(x => x.Topic).Map(x => x.MapKey("Topic_Id")).WillCascadeOnDelete();
HasMany(x => x.TopicNotifications).WithRequired(x => x.Topic).Map(x => x.MapKey("Topic_Id")).WillCascadeOnDelete();
HasMany(t => t.Tags)
    .WithMany(t => t.Topics)
    .Map(m =>
                {
                    m.ToTable("Topic_Tag");
                    m.MapLeftKey("TopicTag_Id");
                    m.MapRightKey("Topic_Id");
                });

これはすべて順調です。しかし、場合によっては、Topic.PostsとTopic.Favoritesを手動で設定する必要があります。

しかし、Topic.Posts = SomeCollectionそれは遅延ロードをトリガーし、最初にすべての投稿をロードしてから、コレクションを設定して2セットのsqlを実行させます(最初は不要です)

とにかく、コレクションを手動で設定したいときにオンデマンドで遅延読み込みを手動でオフに切り替えることはできますか?

理にかなっていることを願っています...:/

25
leen3o

デフォルトで遅延ロードをオフにして、最初に追加データをロードするタイミングを指定する方が良いでしょう。 EFは、クエリで.Include()関数を使用してEagerロードを許可するように設定されていますが、遅延ロードでは、さまざまな機能でオン/オフを開始すると乱雑になる可能性があります。データをオフにする必要があると感じた場合に、どのようなときにデータをロードするか。

https://msdn.Microsoft.com/en-nz/data/jj574232.aspx を参照してください。具体的な例と、データを積極的/遅延的にロードできるさまざまな方法の詳細については、最初の例は、ブログから投稿を引き出す方法を示しています。これは、達成したいものに似ています。

var topics = context.Topics 
                      .Include(t => t.Posts) 
                      .ToList(); 
24
AllMadHare

私はこの正確なシナリオを対象としたアプローチを知らないので、レイジーロードを一時的に無効/有効にする必要があります。

using(var context = new MyContext())
{
    context.Configuration.LazyLoadingEnabled = false;
    // do your thing using .Include() or .Load()
    context.Configuration.LazyLoadingEnabled = true;
}

ただし、これはグローバル構成であるため、シナリオで並行性の問題が発生する可能性があることに注意してください。

16
Jeroen Vannevel

リクエストごとに遅延読み込みをオフにすることはお勧めしません。 AllMadHareが示唆するように、遅延読み込みを完全にオフにすることもできますが、これにより、すべてのデータの読み込み方法を強制的に変更することができます。クラスが次のようになるように、投稿から仮想キーワードを削除することをお勧めします。

public partial class Topic : Entity
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public DateTime CreateDate { get; set; }
    public virtual Post LastPost { get; set; }
    public virtual Category Category { get; set; }
    public IList<Post> Posts { get; set; }
    public virtual IList<TopicTag> Tags { get; set; }
    public virtual MembershipUser User { get; set; }
    public virtual IList<TopicNotification> TopicNotifications { get; set; }
    public virtual IList<Favourite> Favourites { get; set; }
    public virtual Poll Poll { get; set; }
}

ここにあるドキュメントに従って: https://msdn.Microsoft.com/en-us/data/jj574232.aspx#lazyOffProperty これにより、必要に応じて、他のすべてのナビゲーションプロパティを遅延読み込みし、熱心な読み込み投稿を行います。

9
ajliptak

遅延読み込みを使用しているため、クラスとコレクションプロパティに対してプロキシを生成する必要があります。

これらのプロキシコレクションプロパティを独自のコレクションで置き換えることは、私にとって非常に奇妙なデザインのようです。変更の追跡を緩めて、他のいくつかの奇妙な副作用を得る可能性が高いです。

プロキシ/遅延読み込みを使用してコレクションを置き換えるという考えを放棄するか、プロキシの使用を控えて、生成されたPOCOクラスを完全に制御することをお勧めします。

どちらのアプローチがニーズに最も適しているかは、エンティティフレームワークの全体的な使用法によって異なります。

3
Michael Sander