Sql server 选择要使用EF Core列出异步的特定表列

Sql server 选择要使用EF Core列出异步的特定表列,sql-server,.net-core,entity-framework-core,Sql Server,.net Core,Entity Framework Core,我有一个名为CarMakes的表,其中有许多列: 身份证 名字 日期创建 等等 我想检索表中的所有这些记录,但只检索Id和Name列(这样生成的SQL只检索这些特定列)。这也必须异步执行 然而,我可以看到,对于单个实体,它可以异步完成,但是我在弄清楚如何作为异步列表来完成这项工作时遇到了一些困难 我有以下通用方法,它返回任务IEnumerable,其中T是CarMake: public async Task<IEnumerable<T>> GetAllAsync(pa

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

  • 身份证
  • 名字
  • 日期创建
  • 等等
我想检索表中的所有这些记录,但只检索Id和Name列(这样生成的SQL只检索这些特定列)。这也必须异步执行

然而,我可以看到,对于单个实体,它可以异步完成,但是我在弄清楚如何作为异步列表来完成这项工作时遇到了一些困难

我有以下通用方法,它返回任务
IEnumerable
,其中
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;
}
公共异步任务GetAllAsync(参数表达式[]导航属性) { IQueryable query=Context.Set(); query=navigationProperties.Aggregate(query,(current,navigationProperty)=>current.Include(navigationProperty)); IEnumerable entities=wait query.ToListAsync(); 返回实体; }
如何修改此方法以仅生成sql以获取所需的特定字段?

我想您需要类似的内容。我稍微改变了你的GetAllAsync方法。 例如,我们有一个模型类

class Model
{
    public string Val { get; set; }
}
我将您的方法移动到了一个helper类,并使该方法成为泛型方法。它采用2个泛型类型,1个用于IQueryable类型,1个用于返回类型。方法的第一个参数是expression,我们将在这里传递select expression。第二个是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;
    }
}
静态类助手
{
公共静态异步任务GetAllAsync(表达式选择器,参数表达式[]导航属性)
{
IQueryable query=new EnumerableQuery(new List());
query=navigationProperties.Aggregate(query,(current,navigationProperty)=>current.Include(navigationProperty));
IEnumerable entities=wait query.Select(选择器).toListSync();
返回实体;
}
}
我们将在这里调用这个方法。IQueryable的模型和返回类型的字符串

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

希望这能有所帮助。

我在选择特定列时使用了动态返回类型,从而扩展了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;
}
公共异步任务GetDynamicAsync(表达式,其中,表达式列,
参数表达式[]导航属性)
{
IQueryable query=Context.Set();
query=navigationProperties.Aggregate(query,(current,navigationProperty)=>current.Include(navigationProperty));
dynamic entity=wait query.Where(Where).Select(columns.FirstOrDefaultAsync();
返回实体;
}
这将允许一个通用实现,您可以将需要映射的任何字段映射到实际的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)
        };
}
公共类CarMakeDtoConverter:ITypeConverter
{
公共CarMakeDto转换(对象源、CarMakeDto目标、ResolutionContext上下文)
=>新卡马克托
{
//由于此方法的类只接受对象而不接受动态,因此我们需要通过以下方式访问属性:
//GetType().GetProperty().GetValue()
Id=(int)source.GetType().GetProperty(“Id”).GetValue(source),
名称=(字符串)source.GetType().GetProperty(“名称”).GetValue(源)
};
}
因此,您可以在上层使用以下实现:

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;
}
public异步任务GetCarMakeDto(int-id)
{
var result=await GetDynamicAsync(x=>x.Id==Id,x=>new{x.Id,x.Name});
var carMake=Mapper.Map(结果);
返回卡马克;
}

结果选择是
Select()
的工作,而不是
ListAsync()
。您需要向查询添加一个
.Select()
调用,该调用将返回您需要的内容want@PanagiotisKanavos是的,但是如果我使用select,这不会以异步方式运行,因为我无法链接到ToListAsync或类似的异步函数。
select()
不会运行任何东西。它是一个LINQ操作符,就像
Where
GroupBy()
一样。您必须在它之后添加
ToListAsync()
ToArrayAsync()
,才能检索任何需要您花时间解决此问题的内容。非常感谢。没问题,祝你愉快!我已经在自己的回答中详述了你的解决方案。