EntityFramework Eager Загрузить все свойства навигации
Я использую шаблон репозитория с DI и IoC.
Я создал функцию в своем репозитории:
T EagerGetById<T>(Guid id, string include) where T : class
{
return _dbContext.Set<T>().Include(include).Find(id);
}
Это будет загружать одно свойство навигации в мою сущность.
Но если мой объект выглядит так:
public class Blog : PrimaryKey
{
public Author Author {get;set;}
public ICollection<Post> Posts {get;set;}
}
Как мне получить загружаемую загрузку для Author
и Posts
? Должен ли я буквально делать:
_dbContext.Set<T>().Include("Author").Include("Posts").Find(id);
неизбежно создавая такую функцию:
T EagerGetById<T>(Guid id, string include, string include2, string include3) where T : class
{
return _dbContext.Set<T>().Include(include).Include(include2).Include(include3).Find(id);
}
Потому что это было бы действительно неэффективно для репозитория Generic
!
Ответы
Ответ 1
Если вы не хотите использовать строки, вы также можете сделать то же самое для любого N числа включений, используя выражение, которое возвращает свойства навигации, которые нужно загрузить. (исходный источник здесь)
public IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] includeProperties)
{
IQueryable<TEntity> queryable = GetAll();
foreach (Expression<Func<TEntity, object>> includeProperty in includeProperties)
{
queryable = queryable.Include<TEntity, object>(includeProperty);
}
return queryable;
}
Ответ 2
Если вам нужны все свойства навигации, у вас нет выбора, кроме как прочитать все данные из базы данных. Вы либо Include
их в своем запросе, либо читаете их заранее локальным данным DbSet.
Если вы хотите передать несколько включений в свой метод, просто определите его следующим образом:
T EagerGetById<T>(Guid id, params string[] includes)
Ваши пользователи смогут позвонить EagerGetById(id, "inc1", "inc2", ...)
Внутри вашего метода просто вызовите Include
для каждого элемента массива includes
.
Вы должны подготовить ключевое слово params