选择特定的表列以使用EF Core列出异步

时间:2019-02-26 09:28:54

标签: sql-server .net-core entity-framework-core

我有一个名为CarMakes的表,其中包含许多列:

  • 编号
  • 名称
  • DateCreated
  • 等。

我想检索表中的所有这些记录,但只检索Id和Name列(这样,生成的SQL仅检索这些特定的列)。这也必须异步执行。

但是,我可以看到它可以对单个实体进行异步处理,但是在确定如何将其作为异步列表进行处理时遇到了一些麻烦。

我有以下通用方法可返回任务IEnumerable<T>,其中TCarMake

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 :(得分:1)

我认为您想要这样的东西。我稍微修改了GetAllAsync方法。 例如,我们有Model类。

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

我将您的方法移到了帮助器类,并使方法变得通用。它需要2个通用类型,1个用于IQueryable类型,1个用于返回类型。该方法的第一个参数是表达式,我们将在此处传递选择表达式。第二个是您的navigationProperties。

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:...);
}

希望这会有所帮助。

答案 1 :(得分:0)

在选择特定列时,我通过使用动态返回类型扩展了易卜拉欣兹贡的答案:

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;
}