Entity Framework-есть ли способ автоматически загружать дочерние сущности без Include()?


есть ли способ украсить ваши классы 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 поддерживает подобную функциональность.

просто интересно, если я что-то упускаю. Спасибо вперед!

спасибо,

Натан

мне нравится решение ниже, но мне интересно, если я могу вложить вызовы методов расширения. например, скажем, у меня есть аналогичная ситуация с двигателем, где он имеет много частей, которые я не хочу включать везде. Могу ли я сделать что-то подобное? (Я еще не нашел способ для этого работать). Таким образом, если позже я узнаю, что двигатель нуждается в топливных инжекторах, я могу добавить его только в BuildEngine и не должен также добавьте его в BuildCar. кроме того, если я могу вложить вызовы, как я могу вложить вызов в коллекцию? Как вызвать BuildWheel () для каждого из моих колес из моего BuildCar ()?

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);
}

вот еще один очень похожий поток в случае, если он полезен кому-либо еще в этой ситуации, но он все еще не справляется с возможностью совершать следующие вызовы методов расширения.

Entity framework linq query Include () несколько дочерних сущностей

2 64

2 ответа:

Нет ты не может сделать это в отображении. Типичным обходным путем является простой метод расширения:

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;

Edit:

вы не можете вложить вызовы таким образом. Включить работы над основной сущностью, с которой вы работаете - эта сущность определяет форму запроса, поэтому после вызова 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) потому что он должен быть добавлен автоматически при запросе нетерпеливой загрузки его вложенных объектов.

остерегайтесь сложных запросов, создаваемых такими сложными нетерпеливыми структурами загрузки. Это может привести к очень низкой производительности и много дубликатов переданных данных из базы данных.

имел эту же проблему и видел другую ссылку, которая упоминала