Home > Software design >  How to select column from string in efcore?
How to select column from string in efcore?

Time:06-30

I am looking for a solution to select a single column based on the column name. The type of columns I want to select is always string. Like so:

_dbContext.MyModel.Select("Name")...

I wanted to create a extension method:

_dbContext.MyModel.SelectFromString("Name")

It should allow nested selects, like:

_dbContext.MyModel.SelectFromString("Child.Name")

Extension method:

public static IQueryable<T> SelectFromString<T>(this IQueryable<T> query, string column)
{
    var parameter = Expression.Parameter(typeof(T));
    var property = Expression.Property(parameter, column);
    
    //...

    return query.Select(lambda);
}

Not sure how to create the lambda. Any ideas?

CodePudding user response:

The following method projects any property to string and returns IQueryable<string>. Nested properties also supported.

public static class QueryableExtensions
{
    public static IQueryable<string> SelectFromString<T>(this IQueryable<T> query, string column)
    {
        var parameter = Expression.Parameter(typeof(T), "e");
        var property = MakePropPath(parameter, column);

        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)
    {
        return path.Split('.').Aggregate(objExpression, Expression.PropertyOrField);
    }

    private static MethodInfo _toStringMethod = typeof(Convert).GetMethods()
        .Single(m =>
            m.Name == nameof(Convert.ToString) && m.GetParameters().Length == 1 &&
            m.GetParameters()[0].ParameterType == typeof(object)
        );
}
  • Related