Ядро EF: как загружать данные из таблицы и связанных таблиц в общий репозиторий

#c# #entity-framework-core #repository-pattern

#c# #entity-framework-core #репозиторий-шаблон

Вопрос:

Я создал a Generic Repository , который может помочь мне в моих проектах.

Проблема:

В эти дни я работаю над проектом и хочу получить данные из некоторых связанных таблиц (все данные из одной таблицы, а также загрузить все связанные данные из других таблиц, которые я выбираю), созданный мной репозиторий не может справиться с этим, и я не хочу работать напрямую с Entity Framework Core.

Мой репозиторий:

Мой репозиторий — это проект с открытым исходным кодом, вы можете посмотреть исходный код здесь.

Чего я хочу именно:

Моя идея состоит в том, чтобы создать метод в my generic repository , этот метод получит объект, из которого я хочу выбрать данные, и получит выражение, которое сообщает ему загружать данные из объекта scent и некоторых связанных таблиц (не все связанные таблицы, а некоторые связанные таблицы, которые я отправлю в выражении).

Как я могу это решить?

Комментарии:

1. Если шаблон репозитория мешает, не используйте его….

Ответ №1:

Это сильно зависит от вашей конкретной реализации общего репозитория, но следующий код может помочь вам понять идею —

 public async Task<TEntity> LoadSingleWithRelatedAsync<TEntity>(TEntity entity, params Expression<Func<TEntity, object>>[] expressionList) where TEntity : EntityBase
{
    if (entity == null)
        return null;

    var query = _DbCtx.Set<TEntity>().AsQueryable();
    foreach (var expression in expressionList)
    {
        query = query.Include(expression);
    }

    return await query.FirstOrDefaultAsync(p => p.Id == entity.Id);
}
 

где EntityBase

 public class EntityBase
{
    public int Id { get; set; }
}
 

Ниже приведен пример того, как вы могли бы его использовать —

 // Order has a Customer parent and a list of OrderLine children
var loadedOrder = await _Repo.LoadSingleWithRelatedAsync(order, p => p.Customer, p => OrderLines);
 
  1. Order должен быть класс, производный от EntityBase
  2. order может быть Detached объектом (например, полученным через параметр метода со стороны клиента) или уже существующим объектом, извлеченным из базы данных

РЕДАКТИРОВАТЬ: 2021.04.01
Если вам нужна коллекция вместо одного объекта, метод может выглядеть следующим образом —

 public async Task<IEnumerable<TEntity>> LoadAllWithRelatedAsync<TEntity>(params Expression<Func<TEntity, object>>[] expressionList) where TEntity : class
{
    var query = _DbCtx.Set<TEntity>().AsQueryable();
    foreach (var expression in expressionList)
    {
        query = query.Include(expression);
    }

    return await query.ToListAsync();
}
 

Здесь —

  1. TEntity не требуется иметь ограничение EntityBase типа, поскольку мы не используем это Id свойство
  2. Параметр entity не нужен, поскольку мы не ищем конкретную сущность
  3. Чтобы идентифицировать тип в вызывающем коде, параметр type должен использоваться при вызове метода —
 // Order has a Customer parent and a list of OrderLine children
var orderList = await _Repo.LoadAllWithRelatedAsync<Order>(p => p.Customer, p => OrderLines);
 

Комментарии:

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

2. @DEV Пожалуйста, проверьте EDIT .

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

4. @DEV Я обновил сообщение и код, пожалуйста, проверьте. В коде вашего ответа есть проблема — ToList() возвращает новый список при каждом вызове, поэтому result вы получите только последний включенный связанный объект. Вы тестировали код?

5.Пожалуйста, не могли бы вы обновить свой ответ, чтобы вернуть список записей из отправленных entity , а также загрузить все связанные объекты, потому что мне list вообще нужны записи, а также еще один вопрос, если я не буду использовать baseEntity Id то, что я могу сделать? и действительно огромное спасибо