我有一个名为CarMakes的表,其中包含许多列:
我想检索表中的所有这些记录,但只检索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以获取所需的特定字段?
答案 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;
}