Ho una tabella chiamata CarMakes con un numero di colonne:
Vorrei recuperare tutti questi record nella tabella, ma solo le colonne Id e Name (in modo tale che l'SQL generato recuperi solo queste colonne specifiche). Anche questo deve essere eseguito in modo asincrono.
Tuttavia, posso vedere che può essere fatto asincrono per singole entità, ma ho qualche problema a capire come farlo come un elenco asincrono.
Ho il seguente metodo generico che restituisce un'attività di IEnumerable<T>
dove 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;
}
Come modifico questo metodo per generare solo sql per ottenere i campi specifici che desidero?
Ho ampliato la risposta di ibrahimozgon utilizzando un tipo di ritorno dinamico quando si selezionano colonne specifiche:
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;
}
Ciò consentirà un'implementazione generica in cui è possibile mappare tutti i campi che devono essere mappati su un oggetto DTO o sottoclasse simile:
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)
};
}
Quindi puoi utilizzare la seguente implementazione nei tuoi livelli superiori:
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;
}
Penso che tu voglia qualcosa di simile. Ho modificato un po 'il tuo metodo GetAllAsync. Solo, per esempio, abbiamo una classe Model.
class Model
{
public string Val { get; set; }
}
Ho spostato il tuo metodo in una classe helper e ho reso il metodo generico. Sono necessari 2 tipi generici, 1 per IQueryable, 1 per il tipo restituito. il primo parametro del metodo è espressione, passeremo qui l'espressione select. la seconda è la tua navigazioneProperties.
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;
}
}
E chiameremo il metodo qui. Modello per IQueryable e stringa per il tipo restituito.
private static async Task MainAsync(string[] args)
{
var result = await Helper.GetAllAsync<Model, string>(s => s.Val,navigationProperties:...);
}
Spero che questo ti aiuti.