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

Есть ли способ декорировать ваши классы POCO для автоматической загрузки дочерних объектов без необходимости использовать Include() каждый раз, когда вы загружаете их ?

Скажем, у меня есть автомобиль класса Class со сложными типами свойств для колес, дверей, двигателя, бампера, окон, выхлопа и т. д. И в моем приложении мне нужно загрузить свой автомобиль из моего 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. Кроме того, если я могу вкладывать вызовы, как я могу вкладывать вызов в коллекцию? Хотите вызвать 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 Включить () несколько дочерних объектов

65 голосов | спросил Nathan Geffers 25 Jam1000000amFri, 25 Jan 2013 02:49:27 +040013 2013, 02:49:27

2 ответа


0

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

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) вы все еще работаете с ---- +: = 4 =: + ----, и вы не можете вызвать метод расширения для 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); } , потому что оно должно быть добавлено автоматически, когда вы запрашиваете готовую загрузку его вложенных объектов.

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

ответил Ladislav Mrnka 25 Jpm1000000pmFri, 25 Jan 2013 15:31:16 +040013 2013, 15:31:16
0

Возникла такая же проблема, и увидел другую ссылку, в которой упоминался атрибут Include. Мое решение предполагает, что вы создали атрибут с именем IncludeAttribute. С помощью следующего метода расширения и служебного метода :

    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));
    }
ответил Lunyx 18 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 18 Sep 2017 20:31:43 +0300 2017, 20:31:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132