3

特に「大規模な」データグリッドに対して生成される SQL クエリの数を最小限に抑えるために、(.Include() を使用して) 関連するエンティティを熱心に読み込みます。POCO では、関連するエンティティはパブリックな仮想ナビゲーション プロパティです。つまり、それらは遅延ロードされます。プロジェクトの他の部分に最も適しているため、これらの関連エンティティを遅延読み込みするデフォルトの動作を維持したいと考えています。

さて、関連するエンティティをeager-loadした後でも、かなりの量のクエリが生成されていることがわかります。そして、これは関連するエンティティが nullである場合のみのクエリです(SQL 結合が関連するデータを「見つけられなかった」ため、null になります)。

これにより、後でプレゼンテーション層でそれらにアクセスするとすぐに、EF がそれらのエンティティを (まだ読み込まれていないと考えて) 遅延読み込みしようとしていると信じるようになりました。

何か基本的なことを見逃していますか、またはこの問題を回避する方法はありますか?

サンプル コード
リポジトリ パターンを使用して、いくつかの単純化された方法 (ページング、並べ替え、フィルタリングなどを省略) を次に示します。

汎用リポジトリの Get メソッド

public IEnumerable<T> Get(
    Expression<Func<T, object>>[] includes = null)
{
    IQueryable<T> query = set;

    ...

    // Include properies for eager loading
    if (includes != null)
    {
       query = includes.Aggregate(query, 
          (current, include) => current.Include(include));
    }

    ...

    return query.ToList();
}

上記はサービスクラスから呼び出され、このようなものです

...
context.Licenses.Get(
    includes: new Expression<Func<License, object>>[] { l => l.Comment }
);
...

ライセンス POCO

public class License
{
    public License()
    {
    }

    // Primitive properties
    public string ID { get; set; }
    public string Name { get; set; }
    ...
    // Navigation properties
    public virtual LicenseComment Comment { get; set; }
    ...
}

ライセンスコメント POCO

public class LicenseComment
{
    public LicenseComment()
    {
    }

    // Primitive properties
    public string LicenseID { get; set; }
    public string Comment { get; set; }
}

MVC Razor ビュー (またはそのためのモデル) でプロパティにアクセスする

<span>@license.Comment</span>


null の License.Comment にアクセスしようとすると (SQL Server Profiler で調べた)、追加の SQL クエリが生成されます。これは、このプロパティを熱心に含めたにもかかわらず、Entity Framework の遅延読み込みが開始されたように思えます。

4

3 に答える 3

2

試してみることはできませんが、これは起こらないはずです。とにかく、遅延読み込みを発生させたくないページがある場合は、そのページを単にオフにすることができます:

context.Configuration.LazyLoadingEnabled = false;

または、これらのクエリのプロキシ作成をオフにすることができます。プロキシされていないエンティティは遅延読み込みを使用できません。

context.Configuration.ProxyCreationEnabled = false;
于 2012-07-27T08:02:10.437 に答える
1

私は@Ladislavに同意し、それは起こらないはずであり、「通常の」動作は次のとおりであることをテストしました:

コメント付きのライセンスを読み込むと・・・

var license = context.Licenses.Include(l => l.Comment).Single(l => l.ID == 1);

...EF は、ナビゲーション プロパティを読み込み済みとしてマークします。

var isCommentLoaded = context.Entry(license).Reference(l => l.Comment).IsLoaded;

コメントの有無に関係nullなく、プロパティにアクセスするときに遅延読み込みクエリは発行されませんisCommentLoadedtrueComment

熱心な読み込みを使用しなくても...

var license = context.Licenses.Single(l => l.ID == 1);

...データベース内のライセンスからコメントへの外部キーisCommentLoadedがのtrue 場合NULL(ただしfalse、外部キーが でない場合はそうなりますNULL)。その理由は、EF は常にSELECTステートメント内の外部キーをコンテキストに読み込み、このキーがNULLEF の場合、関連するコメントがデータベースにないことを EF が認識し、不要な遅延読み込みを避けるために、ナビゲーション プロパティを既に読み込まれているものとしてマークするためです。

于 2012-07-27T12:32:32.913 に答える