Повторно использовать операторы include в Entity Framework Core - PullRequest
1 голос
/ 30 апреля 2020

Я пытаюсь сделать многоразовые включения, и в настоящее время это работает, когда у меня есть конкретная c конкретная root сущность. Но скажем, у меня есть такая структура:

public class A
{
    public B NavigationB { get; set; }
}

public class B
{
    public C NavigationC { get; set; }
}

public class C
{

}

И мои включаемые расширения

public static class IncludeExtensions
{
    public static IQueryable<B> MyIncludesB(this IQueryable<B> query)
    {
        return query.Include(q => q.NavigationC);
    }

    public static IQueryable<A> MyIncludesA(this IQueryable<A> query)
    {
        return query.Include(q => q.NavigationB)
            .MyIncludesB(); // how can I implement this
    }
}

В принципе все в порядке, если у меня один root например A, но что если Я хочу сделать выборку, используя root B? Идея состоит в том, чтобы затем включить все необходимое для B, но при использовании A в качестве root затем включить все для A, а при включении B повторно использовать MyIncludesB.

I Я не уверен, возможно ли это, потому что include возвращает IIncludableQueryable<A, B>, но если у кого-то есть предложения, не стесняйтесь помочь!

1 Ответ

0 голосов
/ 05 мая 2020

Я думаю, что существует множество возможностей.

Моя первая идея заключалась бы в инкапсуляции выражения свойства:

public static class IncludeExtensions
{
    public static Expression<Func<B, C>> MyIncludeListB()
    {
        return q => q.NavigationC;
    }

    public static Expression<Func<A, B>> MyIncludeListA()
    {
        return q => q.NavigationB;
    }

    public static IQueryable<B> MyIncludesB(this IQueryable<B> query)
    {
        return query.Include(MyIncludeListB());
    }

    public static IQueryable<A> MyIncludesA(this IQueryable<A> query)
    {
        return query.Include(MyIncludeListA()).ThenInclude(MyIncludeListB());
    }
}

Как видите, вы можете передать Expression<Func<B, C>> методу Include

Моя вторая идея состоит в том, чтобы включить include со строками .Include(string):

public static class IncludeExtensions2
{
    public static IEnumerable<string> MyIncludeListB()
    {
        return "NavigationC".Split(";");
    }

    public static IEnumerable<string> MyIncludeListA()
    {
        return "NavigationB;NavigationB.NavigationC".Split(";");
    }

    public static IQueryable<B> MyIncludesB(this IQueryable<B> query)
    {
        foreach (var i in MyIncludeListB())
        {
            query = query.Include(i);
        }

        return query;
    }

    public static IQueryable<A> MyIncludesA(this IQueryable<A> query)
    {
        foreach (var i in MyIncludeListA())
        {
            query = query.Include(i);
        }

        return query;
    }
}

Как видите, вы можете передать string методу Include. Вы можете передать всю цепочку навигационных свойств.

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

Уже есть некоторые вопросы и ответы, подобные вашему :

Easy: Entity Framework - включает несколько уровней свойств

Hard: Несколько включений () в EF Core

...