79

POCO クラスを装飾して、子エンティティをロードするInclude()たびに使用することなく自動的に子エンティティを熱心にロードする方法はありますか?

ホイール、ドア、エンジン、バンパー、窓、排気などの複雑な型のプロパティを持つクラスカーがあるとします。私のアプリでは、DbContext 20 の異なる場所からさまざまなクエリを使用して車をロードする必要があります。車をロードするたびに、すべてのプロパティを含めるように指定する必要はありません。

私は言いたい

List<Car> cars = db.Car
                .Where(x => c.Make == "Ford").ToList();

//NOT .Include(x => x.Wheels).Include(x => x.Doors).Include(x => x.Engine).Include(x => x.Bumper).Include(x => x.Windows)


foreach(Car car in cars)
{

//I don't want a null reference here.

String myString = car.**Bumper**.Title;
}

どういうわけかPOCOクラスを装飾したりOnModelCreating()、EFで構成を設定したりして、車をロードするときに車のすべての部品をロードするように指示することはできますか? 私はこれを熱心にやりたいと思っているので、私の理解では、ナビゲーション プロパティを仮想化することはできません。NHibernate が同様の機能をサポートしていることは知っています。

私は何かが足りないのだろうかと思っています。前もって感謝します!

乾杯、

ネイサン

以下のソリューションは気に入っていますが、拡張メソッドの呼び出しをネストできるかどうか疑問に思っています。たとえば、Engine にも同様の状況があり、どこにも含めたくない多くのパーツがあるとします。このようなことはできますか?(これを機能させる方法はまだ見つかりません)。こうすれば、後で Engine に FuelInjectors が必要であることがわかった場合、BuildEngine にのみ追加でき、BuildCar にも追加する必要はありません。また、呼び出しをネストできる場合、コレクションへの呼び出しをネストするにはどうすればよいですか? BuildCar() 内から各ホイールに対して BuildWheel() を呼び出したいですか?

public static IQueryable<Car> BuildCar(this IQueryable<Car> query) {
     return query.Include(x => x.Wheels).BuildWheel()
                 .Include(x => x.Doors)
                 .Include(x => x.Engine).BuildEngine()
                 .Include(x => x.Bumper)
                 .Include(x => x.Windows);
}

public static IQueryable<Engine> BuildEngine(this IQueryable<Engine> query) {
     return query.Include(x => x.Pistons)
                 .Include(x => x.Cylendars);
}

//Or to handle a collection e.g.
 public static IQueryable<Wheel> BuildWheel(this IQueryable<Wheel> query) {
     return query.Include(x => x.Rim)
                 .Include(x => x.Tire);
}

この状況で他の人に役立つ場合に備えて、非常によく似た別のスレッドを次に示しますが、拡張メソッドへの次の呼び出しを行うことができることをまだ処理していません。

エンティティフレームワークlinqクエリInclude()複数の子エンティティ

4

4 に答える 4

67

いいえ、マッピングではできません。典型的な回避策は、単純な拡張方法です。

public static IQueryable<Car> BuildCar(this IQueryable<Car> query) {
     return query.Include(x => x.Wheels)
                 .Include(x => x.Doors)
                 .Include(x => x.Engine)
                 .Include(x => x.Bumper)
                 .Include(x => x.Windows);
}

Carすべてのリレーションでクエリを実行するたびに、次のようにします。

var query = from car in db.Cars.BuildCar()
            where car.Make == "Ford"
            select car;

編集:

そのように呼び出しをネストすることはできません。インクルードは、使用しているコア エンティティで機能します。そのエンティティはクエリの形状を定義するため、呼び出した後Include(x => Wheels)も作業を続け、IQueryable<Car>の拡張メソッドを呼び出すことはできませんIQueryable<Engine>。でもう一度開始する必要がありますCar

public static IQueryable<Car> BuildCarWheels(this IQuerable<Car> query) {
    // This also answers how to eager load nested collections 
    // Btw. only Select is supported - you cannot use Where, OrderBy or anything else
    return query.Include(x => x.Wheels.Select(y => y.Rim))
                .Include(x => x.Wheels.Select(y => y.Tire));
}

この方法を次のように使用します。

public static IQueryable<Car> BuildCar(this IQueryable<Car> query) {
     return query.BuildCarWheels()
                 .Include(x => x.Doors)
                 .Include(x => x.Engine)
                 .Include(x => x.Bumper)
                 .Include(x => x.Windows);
}

Include(x => x.Wheels)ネストされたエンティティの熱心な読み込みを要求すると自動的に追加されるため、使用法は呼び出されません。

このような複雑な熱心な読み込み構造によって生成される複雑なクエリに注意してください。パフォーマンスが非常に低下し、データベースから大量の重複データが転送される可能性があります。

于 2013-01-25T11:31:16.757 に答える