Выберите конкретные столбцы таблицы для асинхронного списка, используя EF Core - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть таблица CarMakes с несколькими столбцами:

  • Id
  • Имя
  • Дата создания
  • и т. Д.

Я хотел бы получить все эти записи в таблице, но только столбцы Id и Name (чтобы сгенерированный SQL получал только эти конкретные столбцы).Это также должно выполняться асинхронно.

Тем не менее, я вижу, что это может быть сделано асинхронно для отдельных объектов, но у меня возникли некоторые затруднения с выяснением, как сделать это в виде асинхронного списка.

У меня есть следующий универсальный метод, который возвращает задачу IEnumerable<T>, где T равно CarMake:

public async Task<IEnumerable<T>> GetAllAsync(params Expression<Func<T, object>>[] navigationProperties)
{
    IQueryable<T> query = Context.Set<T>();
    query = navigationProperties.Aggregate(query, (current, navigationProperty) => current.Include(navigationProperty));
    IEnumerable<T> entities = await query.ToListAsync();
    return entities;
}

Как бы я изменил этот метод, чтобы генерировать только sql, чтобы получить конкретные поля, которые я хочу

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

Я расширил ответ ibrahimozgon, используя динамический тип возврата при выборе определенных столбцов:

public async Task<dynamic> GetDynamicAsync(Expression<Func<T, bool>> where, Expression<Func<T, dynamic>> columns,
    params Expression<Func<T, object>>[] navigationProperties)
{
    IQueryable<T> query = Context.Set<T>();
    query = navigationProperties.Aggregate(query, (current, navigationProperty) => current.Include(navigationProperty));
    dynamic entity = await query.Where(where).Select(columns).FirstOrDefaultAsync();
    return entity;
}

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

public class CarMakeDtoConverter : ITypeConverter<object, CarMakeDto>
{
    public CarMakeDto Convert(object source, CarMakeDto destination, ResolutionContext context)
        => new CarMakeDto
        {
            // Because this method's class only takes in object and not dynamic, we need to access the properties via:
            // GetType().GetProperty().GetValue()
            Id = (int)source.GetType().GetProperty("Id").GetValue(source),
            Name = (string)source.GetType().GetProperty("Name").GetValue(source)
        };
}

Итак, вы можете использовать следующую реализацию в ваших верхних слоях:

public async Task<CarMakeDto> GetCarMakeDto(int id)
{
    var result = await GetDynamicAsync(x => x.Id == id, x => new { x.Id, x.Name});
    var carMake = Mapper.Map<CarMakeDto>(result);
    return carMake;
}
0 голосов
/ 26 февраля 2019

Я думаю, вы хотите что-то подобное.Я немного изменил ваш метод GetAllAsync.Например, у нас есть класс Model.

class Model
{
    public string Val { get; set; }
}

Я переместил ваш метод в вспомогательный класс и сделал метод универсальным.Требуется 2 универсальных типа, 1 для типа IQueryable, 1 для возвращаемого типа.первым параметром метода является выражение, здесь мы передадим выражение выбора.второй - ваши свойства Navigation.

static class Helper
{
    public static async Task<IEnumerable<TY>> GetAllAsync<T, TY>(Expression<Func<T, TY>> selector, params Expression<Func<T, object>>[] navigationProperties)
    {
        IQueryable<T> query = new EnumerableQuery<T>(new List<T>());
        query = navigationProperties.Aggregate(query, (current, navigationProperty) => current.Include(navigationProperty));
        IEnumerable<TY> entities = await query.Select(selector).ToListAsync();
        return entities;
    }
}

И мы будем вызывать метод здесь.Модель для IQueryable и строка для возвращаемого типа.

private static async Task MainAsync(string[] args)
{
    var result = await Helper.GetAllAsync<Model, string>(s => s.Val,navigationProperties:...);
}

Надеюсь, это поможет.

...