Programing

Entity Framework-Include ()없이 자식 엔터티를 자동으로 즉시로드하는 방법이 있습니까?

crosscheck 2020. 11. 9. 07:48
반응형

Entity Framework-Include ()없이 자식 엔터티를 자동으로 즉시로드하는 방법이 있습니까?


POCO 클래스를 장식하여 자식 엔터티 Include()를로드 할 때마다 사용할 필요없이 자동으로 즉시 로드하는 방법이 있습니까?

Wheels, Doors, Engine, Bumper, Windows, Exhaust 등에 대한 복잡한 유형의 속성을 가진 Class Car가 있다고 가정합니다. 그리고 내 앱에서 다른 쿼리 등으로 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가 유사한 기능을 지원한다는 것을 알고 있습니다.

내가 뭔가를 놓치고 있는지 궁금합니다. 미리 감사드립니다!

건배,

나단

아래 솔루션이 마음에 들지만 확장 메서드에 대한 호출을 중첩 할 수 있는지 궁금합니다. 예를 들어, 내가 어디에나 포함하고 싶지 않은 부품이 많은 엔진과 비슷한 상황이 있다고 가정 해 보겠습니다. 이런 식으로 할 수 있습니까? (아직 작동하는 방법을 찾지 못했습니다). 이렇게하면 나중에 엔진에 FuelInjector가 필요하다는 것을 알게되면 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 () 여러 하위 엔티티


아니요 매핑에서는 그렇게수 없습니다 . 일반적인 해결 방법은 간단한 확장 방법입니다.

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)중첩 된 엔터티의 즉시로드를 요청할 때 자동으로 추가되어야하므로 사용이 호출되지 않습니다 .

Beware of complex queries produced by such complex eager loading structures. It may result in very poor performance and a lot of duplicate data transferred from the database.


Had this same problem and saw the other link which mentioned an Include attribute. My solution assumes that you created an attribute called IncludeAttribute. With the following extension method and utility method:

    public static IQueryable<T> LoadRelated<T>(this IQueryable<T> originalQuery)
    {
        Func<IQueryable<T>, IQueryable<T>> includeFunc = f => f;
        foreach (var prop in typeof(T).GetProperties()
            .Where(p => Attribute.IsDefined(p, typeof(IncludeAttribute))))
        {
            Func<IQueryable<T>, IQueryable<T>> chainedIncludeFunc = f => f.Include(prop.Name);
            includeFunc = Compose(includeFunc, chainedIncludeFunc);
        }
        return includeFunc(originalQuery);
    }

    private static Func<T, T> Compose<T>(Func<T, T> innerFunc, Func<T, T> outerFunc)
    {
        return arg => outerFunc(innerFunc(arg));
    }

참고URL : https://stackoverflow.com/questions/14512285/entity-framework-is-there-a-way-to-automatically-eager-load-child-entities-wit

반응형