.ThenInclude для дочернего объекта в Entity Framework Core 2 - PullRequest
0 голосов
/ 02 мая 2018

Ранее (при использовании .net 4.5.2 и EF 6). У меня был общий Get метод, который принимал ряд включений следующим образом:

public abstract class DataContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDataContext
{
    public DataContext(DbContextOptions options)
    : base(options)
    {
    }

    // reduced for brevity

    public T Get<T>(int id, params Expression<Func<T, object>>[] includes) where T : class, IEntity
    {
        return this.Set<T>().Include(includes).FirstOrDefault(x => x.Id == id);
    }

Я бы тогда позвонил, например;

context.Get<Job>(id, 
    x => x.Equipment,
    x => x.Equipment.Select(y => y.Type));

Чтобы включить Job.Equipment, а также Job.Equipment.Type.

Тем не менее, когда я перенес это на ядро ​​asp.net 2. Я попробовал тот же общий подход, но если я пытаюсь включить дочернюю сущность, я получаю следующую ошибку:

Недопустимое выражение свойства 'x => {от Equipment y в x.Equipment select [y] .Type}'. Выражение должно представлять доступ к свойству: 't => t.MyProperty'. Для получения дополнительной информации о включении связанных данных см. http://go.microsoft.com/fwlink/?LinkID=746393.

Кто-нибудь может подсказать, как я могу обойти это, чтобы включить дочерние сущности в мой общий Get<T> метод с Entity Framework Core 2?

Обновление

При просмотре документов есть дополнительный метод include

include(string navigationPropertyPath)

Я добавил следующий метод;

    public T Get<T>(int id, string[] includes) where T : class, IEntity
    {
        var result = this.Set<T>().AsQueryable();

        foreach(var include in includes)
        {
            result = result.Include(include);
        }

        return result.FirstOrDefault(x => x.Id == id);
    }

Что работает, хотя я не уверен в эффективности здесь?

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Вы можете сделать что-то вроде этого:

   public abstract class DataContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDataContext
    {
        public DataContext(DbContextOptions options)
        : base(options)
        {
        }

        // reduced for brevity

        public T Get<T>(int id, Func<IQueryable<T>, IIncludableQueryable<T, object>> includes = null) where T : class, IEntity
        {
            IQueryable<T> queryable = this.Set<T>();

            if (includes != null)
            {
                queryable = includes(queryable);
            }

            return queryable.FirstOrDefault(x => x.Id == id);
        }
    }

   context.Get<Job>(id, includes: source => source.Include(x => x.Equipment).ThenInclude(x => x.Type));
0 голосов
/ 02 мая 2018
Шаблон

EF Core Include / ThenInclude не может быть представлен Expression<Func<T, object>>[], как в EF6.

Просмотр исходного кода одного из расширений EF Core - Microsoft.EntityFrameworkCore.UnitOfWork , который претендует на

Плагин для Microsoft.EntityFrameworkCore для поддержки репозитория, шаблонов единиц работы и нескольких баз данных с поддержкой распределенных транзакций.

похоже, что предполагаемый шаблон для включений должен основываться на Func<IQueryable<T>, IIncludableQueryable<T, object>>:

public T Get<T>(int id, Func<IQueryable<T>, IIncludableQueryable<T, object>> include = null) where T : class, IEntity
{
    var result = this.Set<T>().AsQueryable();

    if (include != null)
        result = include(result);

    return result.FirstOrDefault(x => x.Id == id);
}

Недостатком является то, что он добавляет зависимость EF Core от вызывающей стороны и требует using Microsoft.EntityFrameworkCore;. Что в вашем случае не имеет значения, так как вы расширяете DbContext.

Использование с вашим примером будет:

context.Get<Job>(id, q => q
    .Include(x => x.Equipment)
        .ThenInclude(y => y.Type));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...