Skip to content

Instantly share code, notes, and snippets.

@cristipufu
Created January 4, 2018 17:46
Show Gist options
  • Save cristipufu/bef7af3658da3a3e65e963e54522ff08 to your computer and use it in GitHub Desktop.
Save cristipufu/bef7af3658da3a3e65e963e54522ff08 to your computer and use it in GitHub Desktop.
OData AutoMapper translate DTO queries to POCO queries
[HttpGet]
public async Task<IEnumerable<AddressModel>> GetAddresses(ODataQueryOptions<AddressModel> queryOptions, CancellationToken cancellationToken)
{
var repository = new AddressRepository(_context);
var service = new AddressService(repository);
var filter = queryOptions.ToModelQueryFilter<AddressModel>();
return await service.QueryByStreetAsync("StreetName", filter, cancellationToken);
}
public Task<List<Address>> QueryByStreetAsync(string street, IQueryFilter<Address> filter, CancellationToken cancellationToken)
{
var query = AsQueryable()
.Apply(filter);
return QueryAsync(query, cancellationToken);
}
public async Task<IEnumerable<AddressModel>> QueryByStreetAsync(
string streetName,
ModelQueryFilter<AddressModel> modelFilter,
CancellationToken cancellationToken)
{
var queryFilter = modelFilter.Map<Address>();
var addresses = await _addressManager.QueryByStreetAsync(streetName, queryFilter, CancellationToken.None);
return addresses.Select(Mapper.Map<AddressModel>);
}
public static class IQueryableExtensions
{
public static IQueryable<T> Apply<T>(this IQueryable<T> query, IQueryFilter<T> filter)
{
if (filter == null) return query;
var action = filter.FilterExpression.Compile();
return action(query);
}
}
public class ModelQueryFilter<TDto>
{
public Expression<Func<IQueryable<TDto>, IQueryable<TDto>>> FilterExpression { get; set; }
public IQueryFilter<TPoco> Map<TPoco>()
{
var expression = Mapper.Instance.Map<Expression<Func<IQueryable<TPoco>, IQueryable<TPoco>>>>(FilterExpression);
return new QueryFilter<TPoco>
{
FilterExpression = expression,
};
}
}
public static class ODataQueryOptionsExtensions
{
public static ModelQueryFilter<TDto> ToModelQueryFilter<TDto>(this ODataQueryOptions options)
{
Expression<Func<IQueryable<TDto>, IQueryable<TDto>>> expression;
var query = (IQueryable<TDto>)options.ApplyTo(Enumerable.Empty<TDto>().AsQueryable());
var param = Expression.Parameter(typeof(IQueryable<TDto>), "x");
if (query.Expression is MethodCallExpression methodCall)
{
var xArg = methodCall.Arguments[1];
var m = methodCall.Update(methodCall.Object, new List<Expression> {param, xArg});
expression = Expression.Lambda<Func<IQueryable<TDto>, IQueryable<TDto>>>(m, param);
}
else
{
expression = x => x;
}
var result = new ModelQueryFilter<TDto>
{
FilterExpression = expression
};
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment