I have an efcore extension, that you find below. It allows me to select using a property path as string:
_dbContext.MyModel.Select("Name")
instead of
_dbContext.MyModel.Select(x => x.Name)
This select returns IQueryable<string>. In addition I want to return the Id of the model. Without an extension it would look like this:
_dbContext.MyModel.Select(x => new { Id = x.Id, Name = x.Name });
I want to be able to call e.g.:
_dbContext.MyModel.Select("Name", withId: true)
and return { Id = x.Id, Name = x.Name }. The source type of Id can be either string or Guid. The destination type should be string. Any idea how to achieve that given the implementation below? The extension could also return { string?, string }, string? being the id.
Efcore extension:
public static IQueryable<string> SelectFromPropertyPath<T>(this IQueryable<T> query, string propertyPath)
{
var parameter = Expression.Parameter(typeof(T), "e");
var property = MakePropPath(parameter, propertyPath);
if (property.Type != typeof(string))
{
if (property.Type != typeof(object))
{
property = Expression.Convert(property, typeof(object));
}
property = Expression.Call(_toStringMethod, property);
}
var lambda = Expression.Lambda<Func<T, string>>(property, parameter);
return query.Select(lambda);
}
private static Expression MakePropPath(Expression objExpression, string path)
=> path.Split('.').Aggregate(objExpression, Expression.PropertyOrField);
private static readonly MethodInfo _toStringMethod = typeof(Convert).GetMethods()
.Single(m =>
m.Name == nameof(Convert.ToString) && m.GetParameters().Length == 1 &&
m.GetParameters()[0].ParameterType == typeof(object)
);
ValueWithIdand returnIQueryable<ValueWithId>